1//////////////////////////////////////////////////////////////////////
2// LibFile: threading.scad
3// Provides generic threading support and specialized support for standard triangular (UTS/ISO) threading,
4// trapezoidal threading (ACME), pipe threading, buttress threading, square threading and ball screws.
5// Includes:
6// include <BOSL2/std.scad>
7// include <BOSL2/threading.scad>
8// FileGroup: Threaded Parts
9// FileSummary: Various types of threaded rods and nuts.
10//////////////////////////////////////////////////////////////////////
11
12
13// Section: Thread Ends and Options
14// A standard process for making machine screws is to begin with round stock that has
15// beveled ends. This stock is then rolled between flat, grooved plates to form the threads.
16// The result is a bolt that looks like this at the end:
17// Figure(3D,Med,NoAxes,VPR=[83.7,0,115.5],VPT=[1.37344,1.26411,-0.299415],VPD=35.5861):
18// threaded_rod(d=13,pitch=2,l=10,blunt_start=false,$fn=80);
19// Figure(2D,Med,NoAxes): A properly mated screw and bolt with beveled ends
20// $fn=32;
21// projection(cut=true)
22// xrot(-90){
23// down(2.5)difference(){
24// cuboid([20,20,5]);
25// zrot(20)
26// threaded_rod(d=13.2, pitch=2,l=5.1,blunt_start=false,internal=true);
27// }
28// up(2.85-2)threaded_rod(d=13, pitch=2, l=10, blunt_start=false);
29//
30// }
31// Continues:
32// Cross threading occurs when the bolt is misaligned with the threads in the nut.
33// It can destroy the threads, or cause the nut to jam. The standard beveled end process
34// makes cross threading a possibility because the beveled partial threads can pass
35// each other when the screw enters the nut.
36// Figure(2D,Med,NoAxes):
37// $fn=32;
38// projection(cut=true)
39// xrot(-90){
40// down(2.5)difference(){
41// cuboid([20,20,5]);
42// zrot(20)
43// threaded_rod(d=13.2, pitch=2,l=5.1,blunt_start=false,internal=true);
44// }
45// left(.6)up(2.99)yrot(-atan(2/13)-1)rot(180+30)threaded_rod(d=13, pitch=2, l=10, blunt_start=false);
46// }
47// Continues:
48// In addition, those partial screw threads may be weak, and easily broken. They do
49// not contribute to the strength of the assembly.
50// In 1891 Clinton A. Higbee received a patent for a modification to screw threads
51// https://patents.google.com/patent/US447775A meant to address these limitations.
52// Instead of beveling the end of the screw, Higbee said to remove the partial thread.
53// The resulting screw might look like this:
54// Figure(3D,Med,NoAxes,VPR=[72,0,294],VPT=[0,0,0],VPD=44):
55// $fn=48;
56// threaded_rod(d=13,pitch=2,l=10,blunt_start=true,lead_in_shape="cut",end_len=.2);
57// Continues:
58// Because the threads are complete everywhere, cross threading is unlikely to occur.
59// This type of threading has been called "Higbee threads", but in recent machinist
60// handbooks it is called "blunt start" threading.
61// This style of thread is not commonly used in metal fasteners because it requires
62// machining the threads, which is much more costly than the rolling procedure described
63// above. However, plastic threads usually have some sort of gradual thread end.
64// For models that will be 3D printed, there is no reason to choose the standard
65// bevel end bolt, so in this library the blunt start threads are the default.
66// If you need standard bevel-end threads, you can choose them with the `blunt_start` options.
67// Note that blunt start threads are more efficient.
68// .
69// Various options exist for controlling the ends of threads. You can specify bevels on threaded rods.
70// In conventional threading, bevels are needed on the ends to remove sharp, thin edges, and
71// the bevel is sized to the full outer diameter of the threaded rod.
72// With blunt start threading, the bevel appears on the unthreaded part of the rod.
73// On a threaded rod, a bevel value of `true` or a positive bevel value cut off the corner.
74// Figure(3D,Med,NoAxes,VPR=[72,0,54],VPT=[0,0,0],VPD=44):
75// threaded_rod(d=13,pitch=2,l=10,blunt_start=true,bevel=true,$fn=80);
76// Continues:
77// A negative bevel value produces a flaring bevel, that might be useful if the rod needs to mate with another part.
78// You can also set `bevel="reverse"` to get a flaring bevel of the default size.
79// Figure(3D,Med,NoAxes,VPR=[72,0,54],VPT=[0,0,0],VPD=44): Negative bevel on a regular threaded rod.
80// threaded_rod(d=13,pitch=2,l=10,blunt_start=true,bevel=-2,$fn=80);
81// Continues:
82// If you set `internal=true` to create a mask for a threaded hole, then bevels are reversed: positive bevels flare outward so that when you subtract
83// the threaded rod it gives a beveled edge to the hole. In this case, negative bevels go inward, which might be useful to
84// create a bevel at the bottom of a threaded hole.
85// Figure(3D,Med,NoAxes,VPR=[72,0,54],VPT=[0,0,0],VPD=44): Threaded rod mask produced using `internal=true` with regular bevel at the top and reversed bevel at the bottom.
86// threaded_rod(d=13,pitch=2,l=10,blunt_start=true,bevel2=true,bevel1="reverse",internal=true,$fn=80);
87// Continues:
88// You can also extend the unthreaded section using the `end_len` parameters. A long unthreaded section will make
89// it impossible to tilt the bolt and produce misaligned threads, so it could make assembly easier.
90// Figure(3D,Med,NoAxes,VPR=[72,0,54],VPT=[0,0,0],VPD=48): Negative bevel on a regular threaded rod.
91// threaded_rod(d=13,pitch=2,l=15,end_len2=5,blunt_start=true,bevel=true,$fn=80);
92// Continues:
93// It is also possible to adjust the length of the lead-in section of threads, or the
94// shape of that lead-in section. The lead-in length can be set using the `lead_in` arguments
95// to specify a length or the `lead_in_ang` arguments to specify an angle. For general
96// threading applications, making the lead in long creates a smaller thread that could
97// be more fragile and more prone to cross threading.
98// Figure(3D,Med,NoAxes,VPR=[52,0,300],VPT=[0,0,4],VPD=35.5861):
99// threaded_rod(d=13,pitch=2,l=10,lead_in=6,blunt_start=true,bevel=false,$fn=80);
100// Continues:
101// To change the form of the thread end you use the `lead_in_shape` argument.
102// You can specify "sqrt", "cut" or "smooth" shapes. The "sqrt" shape is the historical
103// shape used in the library. The "cut" shape is available to model Higbee pattern threads, but
104// is not as good as the others in practice, because the flat faces on the threads can hit each other.
105// The lead-in shape is produced by applying a scale factor to the thread cross section that varies along the lead-in length.
106// You can also specify a custom shape
107// by giving a function literal, `f(x,L)` where `L` will be the total linear
108// length of the lead-in section and `x` will be a value between 0 and 1 giving
109// the position in the lead in, with 0 being the tip and 1 being the full height thread.
110// The return value must be a 2-vector giving the thread width scale and thread height
111// scale at that location. If `x<0` the function must return a thread height scale
112// of zero, but it is usually best if the thread width scale does not go to zero,
113// because that will give a sharply pointed thread end. If `x>1` the function must
114// return `[1,1]`.
115// Figure(3D,Med,NoAxes,VPR=[75,0,338],VPT=[-2,0,3.3],VPD=25): The standard lead in shapes
116// left_half()zrot(0){
117// up(2) threaded_rod(d=13,pitch=2,l=2,blunt_start=true,bevel=false,$fn=128,anchor=BOT);
118// up(4) threaded_rod(d=13,pitch=2,l=2.5,blunt_start=true,bevel=false,$fn=128,lead_in_shape="cut",end_len2=.5,anchor=BOT);
119// threaded_rod(d=13,pitch=2,l=2,blunt_start=true,bevel=false,$fn=128,lead_in_shape="smooth",anchor=BOT);
120// }
121// $fn=64;
122// s=.85;
123// color("black")
124// up(3.5)left(4.5)fwd(6)rot($vpr){
125// back(1.9)text3d("cut",size=s);
126// text3d("sqrt",size=s);
127// fwd(1.9)text3d("smooth",size=s);
128// }
129
130
131// Section: Standard (UTS/ISO) Threading
132
133// Module: threaded_rod()
134// Synopsis: Creates an UTS/ISO triangular threaded rod.
135// SynTags: Geom
136// Topics: Threading, Screws
137// See Also: threaded_nut()
138// Usage:
139// threaded_rod(d, l|length, pitch, [internal=], ...) [ATTACHMENTS];
140// Description:
141// Constructs a standard ISO (metric) or UTS (English) threaded rod. These threads are close to triangular,
142// with a 60 degree thread angle. You can give diameter value which specifies the outer diameter and will produce
143// the "basic form" or you can
144// set d to a triplet [d_min, d_pitch, d_major] where are parameters determined by the ISO and UTS specifications
145// that define clearance sizing for the threading. See screws.scad for how to make screws
146// using the specification parameters.
147// Arguments:
148// d = Outer diameter of threaded rod, or a triplet of [d_min, d_pitch, d_major].
149// l / length / h / height = length of threaded rod.
150// pitch = Length between threads.
151// ---
152// left_handed = if true, create left-handed threads. Default = false
153// starts = The number of lead starts. Default: 1
154// bevel = if true, bevel the thread ends. Default: false
155// bevel1 = if true bevel the bottom end.
156// bevel2 = if true bevel the top end.
157// internal = If true, make this a mask for making internal threads.
158// d1 = Bottom outside diameter of threads.
159// d2 = Top outside diameter of threads.
160// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
161// blunt_start1 = If true apply truncated blunt start threads bottom end.
162// blunt_start2 = If true apply truncated blunt start threads top end.
163// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
164// end_len1 = Specify unthreaded length at the bottom
165// end_len2 = Specify unthreaded length at the top
166// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
167// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
168// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
169// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
170// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
171// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
172// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
173// teardrop = If true, adds a teardrop profile to the back (Y+) side of the threaded rod, for 3d printability of horizontal holes. If numeric, specifies the proportional extra distance of the teardrop flat top from the screw center, or set to "max" for a pointed teardrop. Default: false
174// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
175// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
176// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
177// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
178// Example(2D):
179// projection(cut=true)
180// threaded_rod(d=10, l=15, pitch=1.5, orient=BACK);
181// Examples(Med):
182// threaded_rod(d=25, height=20, pitch=2, $fa=1, $fs=1);
183// threaded_rod(d=10, l=20, pitch=1.25, left_handed=true, $fa=1, $fs=1);
184// threaded_rod(d=25, l=20, pitch=2, $fa=1, $fs=1, end_len=1.5, bevel=true);
185// threaded_rod(d=25, l=20, pitch=2, $fa=1, $fs=1, blunt_start=false);
186// Example(Med;VPR=[100,0,5];VPD=220): Masking a Horizontal Threaded Hole
187// difference() {
188// cuboid(50);
189// threaded_rod(
190// d=25, l=51, pitch=4, $fn=36,
191// internal=true, bevel=true,
192// blunt_start=false,
193// teardrop=true, orient=FWD
194// );
195// }
196// Example(Big,NoAxes): Diamond threading where both left-handed and right-handed nuts travel (in the same direction) on the threaded rod:
197// $fn=32;
198// $slop = 0.075;
199// d = 3/8*INCH;
200// pitch = 1/16*INCH;
201// starts=3;
202// xdistribute(19){
203// intersection(){
204// threaded_rod(l=40, pitch=pitch, d=d,starts=starts,anchor=BOTTOM,end_len=.44);
205// threaded_rod(l=40, pitch=pitch, d=d, left_handed=true,starts=starts,anchor=BOTTOM);
206// }
207// threaded_nut(nutwidth=4.5/8*INCH,id=d,h=3/8*INCH,pitch=pitch,starts=starts,anchor=BOTTOM);
208// threaded_nut(nutwidth=4.5/8*INCH,id=d,h=3/8*INCH,pitch=pitch,starts=starts,left_handed=true,anchor=BOTTOM);
209// }
210function threaded_rod(
211 d, l, pitch,
212 left_handed=false,
213 bevel,bevel1,bevel2,starts=1,
214 internal=false,
215 d1, d2, length, h, height,
216 blunt_start, blunt_start1, blunt_start2,
217 lead_in, lead_in1, lead_in2,
218 lead_in_ang, lead_in_ang1, lead_in_ang2,
219 end_len, end_len1, end_len2,
220 lead_in_shape="default",
221 teardrop=false,
222 anchor, spin, orient
223) = no_function("threaded_rod");
224
225module threaded_rod(
226 d, l, pitch,
227 left_handed=false,
228 bevel,bevel1,bevel2,starts=1,
229 internal=false,
230 d1, d2, length, h, height,
231 blunt_start, blunt_start1, blunt_start2,
232 lead_in, lead_in1, lead_in2,
233 lead_in_ang, lead_in_ang1, lead_in_ang2,
234 end_len, end_len1, end_len2,
235 lead_in_shape="default",
236 teardrop=false,
237 anchor, spin, orient
238) {
239 dummy1=
240 assert(all_positive(pitch))
241 assert(all_positive(d) || (is_undef(d) && all_positive([d1,d2])));
242 basic = is_num(d) || is_undef(d) || is_def(d1) || is_def(d2);
243 dummy2 = assert(basic || is_vector(d,3));
244 depth = basic ? cos(30) * 5/8
245 : (d[2] - d[0])/2/pitch;
246 crestwidth = basic ? 1/8 : 1/2 - (d[2]-d[1])/sqrt(3)/pitch;
247 profile = [
248 [-depth/sqrt(3)-crestwidth/2, -depth],
249 [ -crestwidth/2, 0],
250 [ crestwidth/2, 0],
251 [ depth/sqrt(3)+crestwidth/2, -depth]
252 ];
253 oprofile = internal? [
254 [-6/16, -depth],
255 [-1/16, 0],
256 [-1/32, 0.02],
257 [ 1/32, 0.02],
258 [ 1/16, 0],
259 [ 6/16, -depth]
260 ] : [
261 [-7/16, -depth*1.07],
262 [-6/16, -depth],
263 [-1/16, 0],
264 [ 1/16, 0],
265 [ 6/16, -depth],
266 [ 7/16, -depth*1.07]
267 ];
268 generic_threaded_rod(
269 d=basic ? d : d[2], d1=d1, d2=d2, l=l,
270 pitch=pitch,
271 profile=profile,starts=starts,
272 left_handed=left_handed,
273 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
274 internal=internal, length=length, height=height, h=h,
275 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
276 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
277 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
278 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
279 teardrop=teardrop,
280 anchor=anchor,
281 spin=spin,
282 orient=orient
283 ) children();
284}
285
286
287
288// Module: threaded_nut()
289// Synopsis: Creates an UTS/ISO triangular threaded nut.
290// SynTags: Geom
291// Topics: Threading, Screws
292// See Also: threaded_rod()
293// Usage:
294// threaded_nut(nutwidth, id, h|height|thickness, pitch,...) [ATTACHMENTS];
295// Description:
296// Constructs a hex nut or square nut for an ISO (metric) or UTS (English) threaded rod.
297// The inner diameter is measured from the bottom of the threads.
298// Arguments:
299// nutwidth = flat to flat width of nut
300// id = inner diameter of threaded hole, measured from bottom of threads
301// h / height / l / length / thickness = height/thickness of nut.
302// pitch = Distance between threads, or zero for no threads.
303// ---
304// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
305// left_handed = if true, create left-handed threads. Default = false
306// starts = The number of lead starts. Default: 1
307// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
308// bevel1 = if true, bevel the outside of the nut bottom.
309// bevel2 = if true, bevel the outside of the nut top.
310// bevang = set the angle for the outside nut bevel. Default: 30
311// ibevel = if true, bevel the inside (the hole). Default: true
312// ibevel1 = if true bevel the inside, bottom end.
313// ibevel2 = if true bevel the inside, top end.
314// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
315// blunt_start1 = If true apply truncated blunt start threads bottom end.
316// blunt_start2 = If true apply truncated blunt start threads top end.
317// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
318// end_len1 = Specify unthreaded length at the bottom
319// end_len2 = Specify unthreaded length at the top
320// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
321// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
322// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
323// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
324// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
325// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
326// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
327// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
328// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
329// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
330// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
331// Examples(Med):
332// threaded_nut(nutwidth=16, id=8, h=8, pitch=1.25, $slop=0.05, $fa=1, $fs=1);
333// threaded_nut(nutwidth=16, id=8, h=8, pitch=1.25, left_handed=true, bevel=false, $slop=0.1, $fa=1, $fs=1);
334// threaded_nut(shape="square", nutwidth=16, id=8, h=8, pitch=1.25, $slop=0.1, $fa=1, $fs=1);
335// threaded_nut(shape="square", nutwidth=16, id=8, h=8, pitch=1.25, bevel2=true, $slop=0.1, $fa=1, $fs=1);
336// rot(90)threaded_nut(nutwidth=16, id=8, h=8, pitch=1.25,blunt_start=false, $slop=0.1, $fa=1, $fs=1);
337function threaded_nut(
338 nutwidth, id, h,
339 pitch, starts=1, shape="hex", left_handed=false, bevel, bevel1, bevel2, id1,id2,
340 ibevel1, ibevel2, ibevel, bevang=30, thickness, height,
341 length, l,
342 blunt_start, blunt_start1, blunt_start2,
343 lead_in, lead_in1, lead_in2,
344 lead_in_ang, lead_in_ang1, lead_in_ang2,
345 end_len, end_len1, end_len2,
346 lead_in_shape="default",
347 anchor, spin, orient
348)=no_function("threaded_nut");
349module threaded_nut(
350 nutwidth, id, h,
351 pitch, starts=1, shape="hex", left_handed=false, bevel, bevel1, bevel2, id1,id2,
352 ibevel1, ibevel2, ibevel, bevang=30, thickness, height,
353 length, l,
354 blunt_start, blunt_start1, blunt_start2,
355 lead_in, lead_in1, lead_in2,
356 lead_in_ang, lead_in_ang1, lead_in_ang2,
357 end_len, end_len1, end_len2,
358 lead_in_shape="default",
359 anchor, spin, orient
360) {
361 dummy1=
362 assert(all_nonnegative(pitch), "Nut pitch must be nonnegative")
363 assert(all_positive(id), "Nut inner diameter must be positive")
364 assert(all_positive(h),"Nut thickness must be positive");
365 basic = is_num(id) || is_undef(id) || is_def(id1) || is_def(id2);
366 dummy2 = assert(basic || is_vector(id,3));
367 depth = basic ? cos(30) * 5/8
368 : (id[2] - id[0])/2/pitch;
369 crestwidth = basic ? 1/8 : 1/2 - (id[2]-id[1])/sqrt(3)/pitch;
370 profile = [
371 [-depth/sqrt(3)-crestwidth/2, -depth],
372 [ -crestwidth/2, 0],
373 [ crestwidth/2, 0],
374 [ depth/sqrt(3)+crestwidth/2, -depth]
375 ];
376 oprofile = [
377 [-6/16, -depth/pitch],
378 [-1/16, 0],
379 [-1/32, 0.02],
380 [ 1/32, 0.02],
381 [ 1/16, 0],
382 [ 6/16, -depth/pitch]
383 ];
384 generic_threaded_nut(
385 nutwidth=nutwidth,
386 id=basic ? id : id[2], id1=id1, id2=id2,
387 h=h,
388 pitch=pitch,
389 profile=profile,starts=starts,shape=shape,
390 left_handed=left_handed,
391 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
392 ibevel1=ibevel1, ibevel2=ibevel2, ibevel=ibevel,
393 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
394 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
395 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
396 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
397 l=l,length=length,
398 anchor=anchor, spin=spin,
399 orient=orient
400 ) children();
401}
402
403// Section: Trapezoidal Threading
404
405
406// Module: trapezoidal_threaded_rod()
407// Synopsis: Creates a trapezoidal threaded rod.
408// SynTags: Geom
409// Topics: Threading, Screws
410// See Also: trapezoidal_threaded_nut()
411// Usage:
412// trapezoidal_threaded_rod(d, l|length, pitch, [thread_angle=|flank_angle=], [thread_depth=], [internal=], ...) [ATTACHMENTS];
413// Description:
414// Constructs a threaded rod with a symmetric trapezoidal thread. Trapezoidal threads are used for lead screws because
415// they are one of the strongest symmetric profiles. This tooth shape is stronger than a similarly
416// sized square thread becuase of its wider base. However, it does place a radial load on the nut, unlike the square thread.
417// For loads in only one direction the asymmetric buttress thread profile can bear greater loads.
418// .
419// By default produces the nominal dimensions
420// for metric trapezoidal threads: a thread angle of 30 degrees and a depth set to half the pitch.
421// You can also specify your own trapezoid parameters. For ACME threads see acme_threaded_rod().
422// Figure(2D,Med,NoAxes):
423// pa_delta = tan(15)/4;
424// rr1 = -1/2;
425// z1 = 1/4-pa_delta;
426// z2 = 1/4+pa_delta;
427// profile = [
428// [-z2, rr1],
429// [-z1, 0],
430// [ z1, 0],
431// [ z2, rr1],
432// ];
433// fullprofile = 50*left(1/2,p=concat(profile, right(1, p=profile)));
434// stroke(fullprofile,width=1);
435// dir = fullprofile[2]-fullprofile[3];
436// dir2 = fullprofile[5]-fullprofile[4];
437// curve = arc(32,angle=[75,105],r=67.5);
438// avgpt = mean([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2]);
439// color("red"){
440// stroke([fullprofile[2]+.1*dir, fullprofile[2]+.4*dir], width=1);
441// stroke([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2], width=1);
442// stroke(move(-curve[0]+avgpt,p=curve), width=1,endcaps="arrow2");
443// back(10)text("thread",size=4,halign="center");
444// back(3)text("angle",size=4,halign="center");
445// }
446// Figure(2D,Med,NoAxes):
447// pa_delta = tan(15)/4;
448// rr1 = -1/2;
449// z1 = 1/4-pa_delta;
450// z2 = 1/4+pa_delta;
451// profile = [
452// [-z2, rr1],
453// [-z1, 0],
454// [ z1, 0],
455// [ z2, rr1],
456// ];
457// fullprofile = 50*left(1/2,p=concat(profile, right(1, p=profile)));
458// stroke(fullprofile,width=1);
459// dir = fullprofile[2]-fullprofile[3];
460// dir2 = fullprofile[5]-fullprofile[4];
461// curve = arc(15,angle=[75,87],r=40 /*67.5*/);
462// avgpt = mean([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2]);
463// color("red"){
464// stroke([fullprofile[4]+[0,1], fullprofile[4]+[0,37]], width=1);
465// stroke([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2], width=1);
466// stroke(move(-curve[0]+avgpt,p=curve), width=0.71,endcaps="arrow2");
467// right(14)back(19)text("flank",size=4,halign="center");
468// right(14)back(14)text("angle",size=4,halign="center");
469// }
470// Arguments:
471// d = Outer diameter of threaded rod.
472// l / length / h / height = Length of threaded rod.
473// pitch = Thread spacing.
474// ---
475// thread_angle = Angle between two thread faces. Default: 30
476// thread_depth = Depth of threads. Default: pitch/2
477// flank_angle = Angle of thread faces to plane perpendicular to screw.
478// left_handed = If true, create left-handed threads. Default: false
479// starts = The number of lead starts. Default: 1
480// bevel = if true, bevel the thread ends. Default: false
481// bevel1 = if true bevel the bottom end.
482// bevel2 = if true bevel the top end.
483// internal = If true, make this a mask for making internal threads. Default: false
484// d1 = Bottom outside diameter of threads.
485// d2 = Top outside diameter of threads.
486// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
487// blunt_start1 = If true apply truncated blunt start threads bottom end.
488// blunt_start2 = If true apply truncated blunt start threads top end.
489// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
490// end_len1 = Specify unthreaded length at the bottom
491// end_len2 = Specify unthreaded length at the top
492// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
493// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
494// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
495// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
496// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
497// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
498// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
499// teardrop = If true, adds a teardrop profile to the back (Y+) side of the threaded rod, for 3d printability of horizontal holes. If numeric, specifies the proportional extra distance of the teardrop flat top from the screw center, or set to "max" for a pointed teardrop. Default: false
500// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
501// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
502// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
503// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
504// Example(2D):
505// projection(cut=true)
506// trapezoidal_threaded_rod(d=10, l=15, pitch=2, orient=BACK);
507// Examples(Med):
508// trapezoidal_threaded_rod(d=10, l=40, pitch=2, $fn=32); // Standard metric threading
509// rot(-65)trapezoidal_threaded_rod(d=10, l=17, pitch=2, blunt_start=false, $fn=32); // Standard metric threading
510// trapezoidal_threaded_rod(d=10, l=17, pitch=2, bevel=true, $fn=32); // Standard metric threading
511// trapezoidal_threaded_rod(d=10, h=30, pitch=2, left_handed=true, $fa=1, $fs=1); // Standard metric threading
512// trapezoidal_threaded_rod(d=10, l=40, pitch=3, left_handed=true, starts=3, $fn=36);
513// trapezoidal_threaded_rod(l=25, d=10, pitch=2, starts=3, $fa=1, $fs=1, bevel=true, orient=RIGHT, anchor=BOTTOM);
514// trapezoidal_threaded_rod(d=60, l=16, pitch=8, thread_depth=3, thread_angle=90, blunt_start=false, $fa=2, $fs=2);
515// trapezoidal_threaded_rod(d=60, l=16, pitch=8, thread_depth=3, thread_angle=90, end_len=0, $fa=2, $fs=2);
516// trapezoidal_threaded_rod(d=60, l=16, pitch=8, thread_depth=3, thread_angle=90, left_handed=true, starts=4, $fa=2, $fs=2,end_len=0);
517// trapezoidal_threaded_rod(d=16, l=40, pitch=2, thread_angle=60);
518// trapezoidal_threaded_rod(d=25, l=40, pitch=10, thread_depth=8/3, thread_angle=100, starts=4, anchor=BOT, $fa=2, $fs=2,end_len=-2);
519// trapezoidal_threaded_rod(d=50, l=35, pitch=8, thread_angle=60, starts=11, lead_in=3, $fn=120);
520// trapezoidal_threaded_rod(d=10, l=40, end_len2=10, pitch=2, $fn=32); // Unthreaded top end section
521// Example(Med): Using as a Mask to Make Internal Threads
522// bottom_half() difference() {
523// cube(50, center=true);
524// trapezoidal_threaded_rod(d=40, l=51, pitch=5, thread_angle=30, internal=true, bevel=true, orient=RIGHT, $fn=36);
525// }
526// Example(Med;VPR=[100,0,5];VPD=220): Masking a Horizontal Threaded Hole
527// difference() {
528// cuboid(50);
529// trapezoidal_threaded_rod(
530// d=25, l=51, pitch=4, $fn=36,
531// thread_angle=30,
532// internal=true, bevel=true,
533// blunt_start=false,
534// teardrop=true, orient=FWD
535// );
536// }
537function trapezoidal_threaded_rod(
538 d, l, pitch,
539 thread_angle,
540 thread_depth,
541 flank_angle,
542 left_handed=false,
543 bevel,bevel1,bevel2,
544 starts=1,
545 internal=false,
546 d1, d2, length, h, height,
547 blunt_start, blunt_start1, blunt_start2,
548 lead_in, lead_in1, lead_in2,
549 lead_in_ang, lead_in_ang1, lead_in_ang2,
550 end_len, end_len1, end_len2,
551 lead_in_shape="default",
552 teardrop=false,
553 anchor, spin, orient
554) = no_function("trapezoidal_threaded_rod");
555module trapezoidal_threaded_rod(
556 d, l, pitch,
557 thread_angle,
558 thread_depth,
559 flank_angle,
560 left_handed=false,
561 bevel,bevel1,bevel2,
562 starts=1,
563 internal=false,
564 d1, d2, length, h, height,
565 blunt_start, blunt_start1, blunt_start2,
566 lead_in, lead_in1, lead_in2,
567 lead_in_ang, lead_in_ang1, lead_in_ang2,
568 end_len, end_len1, end_len2,
569 lead_in_shape="default",
570 teardrop=false,
571 anchor, spin, orient
572) {
573 dummy0 = assert(num_defined([thread_angle,flank_angle])<=1, "Cannot define both flank angle and thread angle");
574 thread_angle = first_defined([thread_angle, u_mul(2,flank_angle), 30]);
575 dummy1 = assert(all_nonnegative(pitch),"Must give a positive pitch value")
576 assert(thread_angle>=0 && thread_angle<180, "Invalid thread angle or flank angle")
577 assert(thread_angle<=90 || all_positive([thread_depth]),
578 "Thread angle (2*flank_angle) must be smaller than 90 degrees with default thread depth of pitch/2");
579 depth = first_defined([thread_depth,pitch/2]);
580 pa_delta = 0.5*depth*tan(thread_angle/2) / pitch;
581 dummy2 = assert(pa_delta<=1/4, "Specified thread geometry is impossible");
582 rr1 = -depth/pitch;
583 z1 = 1/4-pa_delta;
584 z2 = 1/4+pa_delta;
585 profile = [
586 [-z2, rr1],
587 [-z1, 0],
588 [ z1, 0],
589 [ z2, rr1],
590 ];
591 generic_threaded_rod(d=d,l=l,pitch=pitch,profile=profile,
592 left_handed=left_handed,bevel=bevel,bevel1=bevel1,bevel2=bevel2,starts=starts,d1=d1,d2=d2,
593 internal=internal, length=length, height=height, h=h,
594 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
595 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
596 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
597 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
598 teardrop=teardrop, anchor=anchor,spin=spin,orient=orient)
599 children();
600}
601
602
603// Module: trapezoidal_threaded_nut()
604// Synopsis: Creates a trapezoidal threaded nut.
605// SynTags: Geom
606// Topics: Threading, Screws
607// See Also: trapezoidal_threaded_rod()
608// Usage:
609// trapezoidal_threaded_nut(nutwidth, id, h|height|thickness, pitch, [thread_angle=|flank_angle=], [thread_depth], ...) [ATTACHMENTS];
610// Description:
611// Constructs a hex nut or square nut for a symmetric trapzoidal threaded rod. By default produces
612// the nominal dimensions for metric trapezoidal threads: a thread angle of 30 degrees and a depth
613// set to half the pitch. You can also specify your own trapezoid parameters. For ACME threads see
614// acme_threaded_nut().
615// Arguments:
616// nutwidth = flat to flat width of nut
617// id = inner diameter of threaded hole, measured from bottom of threads
618// h / height / l / length / thickness = height/thickness of nut.
619// pitch = Thread spacing.
620// ---
621// thread_angle = Angle between two thread faces. Default: 30
622// thread_depth = Depth of the threads. Default: pitch/2
623// flank_angle = Angle of thread faces to plane perpendicular to screw.
624// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
625// left_handed = if true, create left-handed threads. Default = false
626// starts = The number of lead starts. Default = 1
627// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
628// bevel1 = if true, bevel the outside of the nut bottom.
629// bevel2 = if true, bevel the outside of the nut top.
630// bevang = set the angle for the outside nut bevel. Default: 30
631// ibevel = if true, bevel the inside (the hole). Default: true
632// ibevel1 = if true bevel the inside, bottom end.
633// ibevel2 = if true bevel the inside, top end.
634// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
635// blunt_start1 = If true apply truncated blunt start threads bottom end.
636// blunt_start2 = If true apply truncated blunt start threads top end.
637// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
638// end_len1 = Specify unthreaded length at the bottom
639// end_len2 = Specify unthreaded length at the top
640// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
641// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
642// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
643// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
644// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
645// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
646// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
647// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
648// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
649// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
650// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
651// Examples(Med):
652// trapezoidal_threaded_nut(nutwidth=16, id=8, h=8, pitch=2, $slop=0.1, anchor=UP);
653// trapezoidal_threaded_nut(nutwidth=16, id=8, h=8, pitch=2, bevel=false, $slop=0.05, anchor=UP);
654// trapezoidal_threaded_nut(nutwidth=17.4, id=10, h=10, pitch=2, $slop=0.1, left_handed=true);
655// trapezoidal_threaded_nut(nutwidth=17.4, id=10, h=10, pitch=2, starts=3, $fa=1, $fs=1, $slop=0.15);
656// trapezoidal_threaded_nut(nutwidth=17.4, id=10, h=10, pitch=2, starts=3, $fa=1, $fs=1, $slop=0.15, blunt_start=false);
657// trapezoidal_threaded_nut(nutwidth=17.4, id=10, h=10, pitch=0, $slop=0.2); // No threads
658function trapezoidal_threaded_nut(
659 nutwidth,
660 id,
661 h,
662 pitch,
663 thread_angle,
664 thread_depth, shape="hex",
665 flank_angle,
666 left_handed=false,
667 starts=1,
668 bevel,bevel1,bevel2,bevang=30,
669 ibevel1,ibevel2,ibevel,
670 thickness,height,
671 id1,id2,
672 length, l,
673 blunt_start, blunt_start1, blunt_start2,
674 lead_in, lead_in1, lead_in2,
675 lead_in_ang, lead_in_ang1, lead_in_ang2,
676 end_len, end_len1, end_len2,
677 lead_in_shape="default",
678 anchor, spin, orient
679) = no_function("trapezoidal_threaded_nut");
680module trapezoidal_threaded_nut(
681 nutwidth,
682 id,
683 h,
684 pitch,
685 thread_angle,
686 thread_depth, shape="hex",
687 flank_angle,
688 left_handed=false,
689 starts=1,
690 bevel,bevel1,bevel2,bevang=30,
691 ibevel1,ibevel2,ibevel,
692 thickness,height,
693 id1,id2,
694 length, l,
695 blunt_start, blunt_start1, blunt_start2,
696 lead_in, lead_in1, lead_in2,
697 lead_in_ang, lead_in_ang1, lead_in_ang2,
698 end_len, end_len1, end_len2,
699 lead_in_shape="default",
700 anchor, spin, orient
701) {
702 dummy0 = assert(num_defined([thread_angle,flank_angle])<=1, "Cannot define both flank angle and thread angle");
703 thread_angle = first_defined([thread_angle, u_mul(2,flank_angle), 30]);
704 dummy1 = assert(all_nonnegative(pitch),"Must give a positive pitch value")
705 assert(thread_angle>=0 && thread_angle<180, "Invalid thread angle or flank angle")
706 assert(thread_angle<=90 || all_positive([thread_depth]),
707 "Thread angle (2*flank_angle) must be smaller than 90 degrees with default thread depth of pitch/2");
708 depth = first_defined([thread_depth,pitch/2]);
709 pa_delta = 0.5*depth*tan(thread_angle/2) / pitch;
710 dummy2 = assert(pitch==0 || pa_delta<1/4, "Specified thread geometry is impossible");
711 rr1 = -depth/pitch;
712 z1 = 1/4-pa_delta;
713 z2 = 1/4+pa_delta;
714 profile = [
715 [-z2, rr1],
716 [-z1, 0],
717 [ z1, 0],
718 [ z2, rr1],
719 ];
720 generic_threaded_nut(nutwidth=nutwidth,id=id,h=h,pitch=pitch,profile=profile,id1=id1,id2=id2,
721 shape=shape,left_handed=left_handed,bevel=bevel,bevel1=bevel1,bevel2=bevel2,starts=starts,
722 ibevel=ibevel,ibevel1=ibevel1,ibevel2=ibevel2,bevang=bevang,height=height,thickness=thickness,
723 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
724 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
725 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
726 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
727 l=l,length=length,
728 anchor=anchor,spin=spin,orient=orient)
729 children();
730}
731
732
733// Module: acme_threaded_rod()
734// Synopsis: Creates an ACME threaded rod.
735// SynTags: Geom
736// Topics: Threading, Screws
737// See Also: acme_threaded_nut()
738// Usage:
739// acme_threaded_rod(d, l|length, tpi|pitch=, [internal=], ...) [ATTACHMENTS];
740// Description:
741// Constructs an ACME trapezoidal threaded screw rod. This form has a 29 degree thread angle with a
742// symmetric trapezoidal thread.
743// Arguments:
744// d = Outer diameter of threaded rod.
745// l / length / h / height = Length of threaded rod.
746// tpi = threads per inch.
747// ---
748// pitch = thread spacing (alternative to tpi)
749// starts = The number of lead starts. Default = 1
750// left_handed = if true, create left-handed threads. Default = false
751// bevel = if true, bevel the thread ends. Default: false
752// bevel1 = if true bevel the bottom end.
753// bevel2 = if true bevel the top end.
754// internal = If true, this is a mask for making internal threads.
755// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
756// blunt_start1 = If true apply truncated blunt start threads bottom end.
757// blunt_start2 = If true apply truncated blunt start threads top end.
758// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
759// end_len1 = Specify unthreaded length at the bottom
760// end_len2 = Specify unthreaded length at the top
761// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
762// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
763// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
764// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
765// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
766// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
767// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
768// teardrop = If true, adds a teardrop profile to the back (Y+) side of the threaded rod, for 3d printability of horizontal holes. If numeric, specifies the proportional extra distance of the teardrop flat top from the screw center, or set to "max" for a pointed teardrop. Default: false
769// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
770// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
771// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
772// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
773// Example(2D):
774// projection(cut=true)
775// acme_threaded_rod(d=10, l=15, pitch=2, orient=BACK);
776// Examples(Med):
777// acme_threaded_rod(d=3/8*INCH, l=20, pitch=1/8*INCH, $fn=32);
778// acme_threaded_rod(d=10, l=30, pitch=2, starts=3, $fa=1, $fs=1);
779// Example(Med;VPR=[100,0,5];VPD=220): Masking a Horizontal Threaded Hole
780// difference() {
781// cuboid(50);
782// acme_threaded_rod(
783// d=25, l=51, pitch=4, $fn=36,
784// internal=true, bevel=true,
785// blunt_start=false,
786// teardrop=true, orient=FWD
787// );
788// }
789function acme_threaded_rod(
790 d, l, tpi, pitch,
791 starts=1,
792 left_handed=false,
793 bevel,bevel1,bevel2,
794 internal=false,
795 d1, d2, length, h, height,
796 blunt_start, blunt_start1, blunt_start2,
797 lead_in, lead_in1, lead_in2,
798 lead_in_ang, lead_in_ang1, lead_in_ang2,
799 end_len, end_len1, end_len2,
800 lead_in_shape="default",
801 teardrop=false,
802 anchor, spin, orient
803) = no_function("acme_threaded_rod");
804module acme_threaded_rod(
805 d, l, tpi, pitch,
806 starts=1,
807 left_handed=false,
808 bevel,bevel1,bevel2,
809 internal=false,
810 d1, d2, length, h, height,
811 blunt_start, blunt_start1, blunt_start2,
812 lead_in, lead_in1, lead_in2,
813 lead_in_ang, lead_in_ang1, lead_in_ang2,
814 end_len, end_len1, end_len2,
815 lead_in_shape="default",
816 teardrop=false,
817 anchor, spin, orient
818) {
819 dummy = assert(num_defined([pitch,tpi])==1,"Must give exactly one of pitch and tpi");
820 pitch = is_undef(pitch) ? INCH/tpi : pitch;
821 trapezoidal_threaded_rod(
822 d=d, l=l, pitch=pitch,
823 thread_angle=29,
824 thread_depth=pitch/2,
825 starts=starts,
826 left_handed=left_handed,
827 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
828 internal=internal, length=length, height=height, h=h,
829 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
830 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
831 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
832 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
833 teardrop=teardrop,
834 anchor=anchor,
835 spin=spin,
836 orient=orient
837 ) children();
838}
839
840
841
842// Module: acme_threaded_nut()
843// Synopsis: Creates an ACME threaded nut.
844// SynTags: Geom
845// Topics: Threading, Screws
846// See Also: acme_threaded_rod()
847// Usage:
848// acme_threaded_nut(nutwidth, id, h|height|thickness, tpi|pitch=, [shape=], ...) [ATTACHMENTS];
849// Description:
850// Constructs a hexagonal or square nut for an ACME threaded screw rod.
851// Arguments:
852// nutwidth = flat to flat width of nut.
853// id = inner diameter of threaded hole, measured from bottom of threads
854// h / height / l / length / thickness = height/thickness of nut.
855// tpi = threads per inch
856// ---
857// pitch = Thread spacing (alternative to tpi)
858// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
859// left_handed = if true, create left-handed threads. Default = false
860// starts = Number of lead starts. Default: 1
861// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
862// bevel1 = if true, bevel the outside of the nut bottom.
863// bevel2 = if true, bevel the outside of the nut top.
864// bevang = set the angle for the outside nut bevel. Default: 30
865// ibevel = if true, bevel the inside (the hole). Default: true
866// ibevel1 = if true bevel the inside, bottom end.
867// ibevel2 = if true bevel the inside, top end.
868// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
869// blunt_start1 = If true apply truncated blunt start threads bottom end.
870// blunt_start2 = If true apply truncated blunt start threads top end.
871// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
872// end_len1 = Specify unthreaded length at the bottom
873// end_len2 = Specify unthreaded length at the top
874// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
875// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
876// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
877// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
878// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
879// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
880// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
881// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
882// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
883// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
884// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
885// Examples(Med):
886// acme_threaded_nut(nutwidth=16, id=3/8*INCH, h=8, tpi=8, $slop=0.05);
887// acme_threaded_nut(nutwidth=16, id=3/8*INCH, h=10, tpi=12, starts=3, $slop=0.1, $fa=1, $fs=1, ibevel=false);
888// acme_threaded_nut(nutwidth=16, id=3/8*INCH, h=10, tpi=12, starts=3, $slop=0.1, $fa=1, $fs=1, blunt_start=false);
889function acme_threaded_nut(
890 nutwidth, id, h, tpi, pitch,
891 starts=1,
892 left_handed=false,shape="hex",
893 bevel,bevel1,bevel2,bevang=30,
894 ibevel,ibevel1,ibevel2,
895 height,thickness,
896 length, l,
897 blunt_start, blunt_start1, blunt_start2,
898 lead_in, lead_in1, lead_in2,
899 lead_in_ang, lead_in_ang1, lead_in_ang2,
900 end_len, end_len1, end_len2,
901 lead_in_shape="default",
902 anchor, spin, orient
903) = no_function("acme_threaded_nut");
904module acme_threaded_nut(
905 nutwidth, id, h, tpi, pitch,
906 starts=1,
907 left_handed=false,shape="hex",
908 bevel,bevel1,bevel2,bevang=30,
909 ibevel,ibevel1,ibevel2,
910 height,thickness,
911 length, l,
912 blunt_start, blunt_start1, blunt_start2,
913 lead_in, lead_in1, lead_in2,
914 lead_in_ang, lead_in_ang1, lead_in_ang2,
915 end_len, end_len1, end_len2,
916 lead_in_shape="default",
917 anchor, spin, orient
918) {
919 dummy = assert(num_defined([pitch,tpi])==1,"Must give exactly one of pitch and tpi");
920 pitch = is_undef(pitch) ? INCH/tpi : pitch;
921 dummy2=assert(is_num(pitch) && pitch>=0);
922 trapezoidal_threaded_nut(
923 nutwidth=nutwidth, id=id, h=h, pitch=pitch,
924 thread_depth = pitch/2,
925 thread_angle=29,shape=shape,
926 left_handed=left_handed,
927 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
928 ibevel=ibevel,ibevel1=ibevel1,ibevel2=ibevel2,
929 height=height,thickness=thickness,
930 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
931 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
932 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
933 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
934 l=l,length=length,
935 starts=starts,
936 anchor=anchor,
937 spin=spin,
938 orient=orient
939 ) children();
940}
941
942
943
944
945// Section: Pipe Threading
946
947// Module: npt_threaded_rod()
948// Synopsis: Creates NPT pipe threading.
949// SynTags: Geom
950// Topics: Threading, Screws
951// See Also: acme_threaded_rod()
952// Usage:
953// npt_threaded_rod(size, [internal=], ...) [ATTACHMENTS];
954// Description:
955// Constructs a standard NPT pipe end threading. If `internal=true`, creates a mask for making
956// internal pipe threads. Tapers smaller upwards if `internal=false`. Tapers smaller downwards
957// if `internal=true`. If `hollow=true` and `internal=false`, then the pipe threads will be
958// hollowed out into a pipe with the apropriate internal diameter.
959// Arguments:
960// size = NPT standard pipe size in inches. 1/16", 1/8", 1/4", 3/8", 1/2", 3/4", 1", 1+1/4", 1+1/2", or 2". Default: 1/2"
961// ---
962// left_handed = If true, create left-handed threads. Default = false
963// bevel = if true, bevel the thread ends. Default: false
964// bevel1 = if true bevel the bottom end.
965// bevel2 = if true bevel the top end.
966// hollow = If true, create a pipe with the correct internal diameter.
967// internal = If true, make this a mask for making internal threads.
968// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
969// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
970// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
971// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
972// Example(2D): The straight gray rectangle reveals the tapered threads.
973// projection(cut=true) npt_threaded_rod(size=1/4, orient=BACK);
974// right(.533*INCH/2) color("gray") rect([2,0.5946*INCH],anchor=LEFT);
975// Examples(Med):
976// npt_threaded_rod(size=3/8, $fn=72);
977// npt_threaded_rod(size=1/2, $fn=72, bevel=true);
978// npt_threaded_rod(size=1/2, left_handed=true, $fn=72);
979// npt_threaded_rod(size=3/4, hollow=true, $fn=96);
980// Example:
981// diff("remove"){
982// cuboid([40,40,40])
983// tag("remove"){
984// up(.01)position(TOP)
985// npt_threaded_rod(size=3/4, $fn=96, internal=true, $slop=0.1, anchor=TOP);
986// cyl(d=3/4*INCH, l=42, $fn=32);
987// }
988// }
989function npt_threaded_rod(
990 size=1/2,
991 left_handed=false,
992 bevel,bevel1,bevel2,
993 hollow=false,
994 internal=false,
995 anchor, spin, orient
996)=no_function("npt_threaded_rod");
997module npt_threaded_rod(
998 size=1/2,
999 left_handed=false,
1000 bevel,bevel1,bevel2,
1001 hollow=false,
1002 internal=false,
1003 anchor, spin, orient
1004) {
1005 assert(is_finite(size));
1006 assert(is_bool(left_handed));
1007 assert(is_undef(bevel) || is_bool(bevel));
1008 assert(is_bool(hollow));
1009 assert(is_bool(internal));
1010 assert(!(internal&&hollow), "Cannot created a hollow internal threads mask.");
1011 info_table = [
1012 // Size len OD TPI
1013 [ 1/16, [ 0.3896, 0.308, 27 ]],
1014 [ 1/8, [ 0.3924, 0.401, 27 ]],
1015 [ 1/4, [ 0.5946, 0.533, 18 ]],
1016 [ 3/8, [ 0.6006, 0.668, 18 ]],
1017 [ 1/2, [ 0.7815, 0.832, 14 ]],
1018 [ 3/4, [ 0.7935, 1.043, 14 ]],
1019 [ 1, [ 0.9845, 1.305, 11.5]],
1020 [ 1+1/4, [ 1.0085, 1.649, 11.5]],
1021 [ 1+1/2, [ 1.0252, 1.888, 11.5]],
1022 [ 2, [ 1.0582, 2.362, 11.5]],
1023 ];
1024 info = [for (data=info_table) if(approx(size,data[0])) data[1]][0];
1025 dummy1 = assert(is_def(info), "Unsupported NPT size. Try one of 1/16, 1/8, 1/4, 3/8, 1/2, 3/4, 1, 1+1/4, 1+1/2, 2");
1026 l = INCH * info[0];
1027 d = INCH * info[1];
1028 pitch = INCH / info[2];
1029 rr = d/2;
1030 rr2 = rr - l/32;
1031 r1 = internal? rr2 : rr;
1032 r2 = internal? rr : rr2;
1033 depth = pitch * cos(30) * 5/8;
1034 profile = internal? [
1035 [-6/16, -depth/pitch],
1036 [-1/16, 0],
1037 [-1/32, 0.02],
1038 [ 1/32, 0.02],
1039 [ 1/16, 0],
1040 [ 6/16, -depth/pitch]
1041 ] : [
1042 [-7/16, -depth/pitch*1.07],
1043 [-6/16, -depth/pitch],
1044 [-1/16, 0],
1045 [ 1/16, 0],
1046 [ 6/16, -depth/pitch],
1047 [ 7/16, -depth/pitch*1.07]
1048 ];
1049 attachable(anchor,spin,orient, l=l, r1=r1, r2=r2) {
1050 difference() {
1051 generic_threaded_rod(
1052 d1=2*r1, d2=2*r2, l=l,
1053 pitch=pitch,
1054 profile=profile,
1055 left_handed=left_handed,
1056 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
1057 internal=internal,
1058 blunt_start=true
1059 );
1060 if (hollow) cylinder(h=l+1, d=size*INCH, center=true);
1061 }
1062 children();
1063 }
1064}
1065
1066
1067
1068// Section: Buttress Threading
1069
1070// Module: buttress_threaded_rod()
1071// Synopsis: Creates a buttress-threaded rod.
1072// SynTags: Geom
1073// Topics: Threading, Screws
1074// See Also: buttress_threaded_nut()
1075// Usage:
1076// buttress_threaded_rod(d, l|length, pitch, [internal=], ...) [ATTACHMENTS];
1077// Description:
1078// Constructs a simple buttress threaded rod with a 45 degree angle. The buttress thread or sawtooth thread has low friction and high loading
1079// in one direction at the cost of higher friction and inferior loading in the other direction. Buttress threads are sometimes used on
1080// vises, which are loaded only in one direction.
1081// Arguments:
1082// d = Outer diameter of threaded rod.
1083// l / length / h / height = Length of threaded rod.
1084// pitch = Thread spacing.
1085// ---
1086// left_handed = if true, create left-handed threads. Default = false
1087// starts = Number of lead starts. Default: 1
1088// bevel = if true, bevel the thread ends. Default: false
1089// bevel1 = if true bevel the bottom end.
1090// bevel2 = if true bevel the top end.
1091// internal = If true, this is a mask for making internal threads.
1092// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1093// blunt_start1 = If true apply truncated blunt start threads bottom end.
1094// blunt_start2 = If true apply truncated blunt start threads top end.
1095// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1096// end_len1 = Specify unthreaded length at the bottom
1097// end_len2 = Specify unthreaded length at the top
1098// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1099// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1100// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1101// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1102// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1103// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1104// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1105// teardrop = If true, adds a teardrop profile to the back (Y+) side of the threaded rod, for 3d printability of horizontal holes. If numeric, specifies the proportional extra distance of the teardrop flat top from the screw center, or set to "max" for a pointed teardrop. Default: false
1106// d1 = Bottom outside diameter of threads.
1107// d2 = Top outside diameter of threads.
1108// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1109// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1110// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1111// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1112// Example(2D):
1113// projection(cut=true)
1114// buttress_threaded_rod(d=10, l=15, pitch=2, orient=BACK);
1115// Examples(Med):
1116// buttress_threaded_rod(d=25, l=20, pitch=2, $fa=1, $fs=1,end_len=0);
1117// buttress_threaded_rod(d=10, l=20, pitch=1.25, left_handed=true, $fa=1, $fs=1);
1118// Example(Med;VPR=[100,0,5];VPD=220): Masking a Horizontal Threaded Hole
1119// difference() {
1120// cuboid(50);
1121// buttress_threaded_rod(
1122// d=25, l=51, pitch=4, $fn=36,
1123// internal=true, bevel=true,
1124// blunt_start=false,
1125// teardrop=true, orient=FWD
1126// );
1127// }
1128function buttress_threaded_rod(
1129 d, l, pitch,
1130 left_handed=false, starts=1,
1131 bevel,bevel1,bevel2,
1132 internal=false,
1133 d1, d2, length, h, height,
1134 blunt_start, blunt_start1, blunt_start2,
1135 lead_in, lead_in1, lead_in2,
1136 lead_in_ang, lead_in_ang1, lead_in_ang2,
1137 end_len, end_len1, end_len2,
1138 lead_in_shape="default",
1139 teardrop=false,
1140 anchor, spin, orient
1141) = no_function("buttress_threaded_rod");
1142module buttress_threaded_rod(
1143 d, l, pitch,
1144 left_handed=false, starts=1,
1145 bevel,bevel1,bevel2,
1146 internal=false,
1147 d1, d2, length, h, height,
1148 blunt_start, blunt_start1, blunt_start2,
1149 lead_in, lead_in1, lead_in2,
1150 lead_in_ang, lead_in_ang1, lead_in_ang2,
1151 end_len, end_len1, end_len2,
1152 lead_in_shape="default",
1153 teardrop=false,
1154 anchor, spin, orient
1155) {
1156 depth = pitch * 3/4;
1157 profile = [
1158 [ -1/2, -0.77],
1159 [ -7/16, -0.75],
1160 [ 5/16, 0],
1161 [ 7/16, 0],
1162 [ 7/16, -0.75],
1163 [ 1/2, -0.77],
1164 ];
1165 generic_threaded_rod(
1166 d=d, l=l, pitch=pitch,
1167 profile=profile,
1168 left_handed=left_handed,
1169 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
1170 internal=internal, length=length, height=height, h=h,
1171 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
1172 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
1173 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
1174 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
1175 d1=d1,d2=d2,
1176 teardrop=teardrop,
1177 anchor=anchor,
1178 spin=spin,starts=starts,
1179 orient=orient
1180 ) children();
1181}
1182
1183
1184
1185// Module: buttress_threaded_nut()
1186// Synopsis: Creates a buttress-threaded nut.
1187// SynTags: Geom
1188// Topics: Threading, Screws
1189// See Also: buttress_threaded_rod()
1190// Usage:
1191// buttress_threaded_nut(nutwidth, id, h|height|thickness, pitch, ...) [ATTACHMENTS];
1192// Description:
1193// Constructs a hexagonal or square nut for a simple buttress threaded screw rod.
1194// Arguments:
1195// nutwidth = diameter of the nut.
1196// id = inner diameter of threaded hole, measured from bottom of threads
1197// h / height / l / length / thickness = height/thickness of nut.
1198// pitch = Thread spacing.
1199// ---
1200// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
1201// left_handed = if true, create left-handed threads. Default = false
1202// starts = The number of lead starts. Default: 1
1203// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
1204// bevel1 = if true, bevel the outside of the nut bottom.
1205// bevel2 = if true, bevel the outside of the nut top.
1206// bevang = set the angle for the outside nut bevel. Default: 30
1207// ibevel = if true, bevel the inside (the hole). Default: true
1208// ibevel1 = if true bevel the inside, bottom end.
1209// ibevel2 = if true bevel the inside, top end.
1210// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1211// blunt_start1 = If true apply truncated blunt start threads bottom end.
1212// blunt_start2 = If true apply truncated blunt start threads top end.
1213// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1214// end_len1 = Specify unthreaded length at the bottom
1215// end_len2 = Specify unthreaded length at the top
1216// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1217// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1218// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1219// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1220// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1221// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1222// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1223// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1224// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1225// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1226// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1227// Examples(Med):
1228// buttress_threaded_nut(nutwidth=16, id=8, h=8, pitch=1.25, left_handed=true, $slop=0.05, $fa=1, $fs=1);
1229function buttress_threaded_nut(
1230 nutwidth, id, h,
1231 pitch, shape="hex", left_handed=false,
1232 bevel,bevel1,bevel2,bevang=30,starts=1,
1233 ibevel,ibevel1,ibevel2,height,thickness,
1234 length, l,
1235 blunt_start, blunt_start1, blunt_start2,
1236 lead_in, lead_in1, lead_in2,
1237 lead_in_ang, lead_in_ang1, lead_in_ang2,
1238 end_len, end_len1, end_len2,
1239 lead_in_shape="default",
1240 anchor, spin, orient
1241) = no_function("buttress_threaded_nut");
1242module buttress_threaded_nut(
1243 nutwidth, id, h,
1244 pitch, shape="hex", left_handed=false,
1245 bevel,bevel1,bevel2,bevang=30,starts=1,
1246 ibevel,ibevel1,ibevel2,height,thickness,
1247 length, l,
1248 blunt_start, blunt_start1, blunt_start2,
1249 lead_in, lead_in1, lead_in2,
1250 lead_in_ang, lead_in_ang1, lead_in_ang2,
1251 end_len, end_len1, end_len2,
1252 lead_in_shape="default",
1253 anchor, spin, orient
1254) {
1255 depth = pitch * 3/4;
1256 profile = [
1257 [ -1/2, -0.77],
1258 [ -7/16, -0.75],
1259 [ 5/16, 0],
1260 [ 7/16, 0],
1261 [ 7/16, -0.75],
1262 [ 1/ 2, -0.77],
1263 ];
1264 generic_threaded_nut(
1265 nutwidth=nutwidth, id=id, h=h,
1266 pitch=pitch,
1267 profile=profile,
1268 shape=shape,
1269 left_handed=left_handed,starts=starts,
1270 bevel=bevel,bevel1=bevel1,bevel2=bevel2,bevang=bevang,
1271 ibevel=ibevel,ibevel1=ibevel1,ibevel2=ibevel2,
1272 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
1273 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
1274 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
1275 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
1276 l=l,length=length,
1277 anchor=anchor, spin=spin, height=height, thickness=thickness,
1278 orient=orient
1279 ) children();
1280}
1281
1282
1283
1284// Section: Square Threading
1285
1286// Module: square_threaded_rod()
1287// Synopsis: Creates a square-threaded rod.
1288// SynTags: Geom
1289// Topics: Threading, Screws
1290// See Also: square_threaded_nut()
1291// Usage:
1292// square_threaded_rod(d, l|length, pitch, [internal=], ...) [ATTACHMENTS];
1293// Description:
1294// Constructs a square profile threaded screw rod. The greatest advantage of square threads is
1295// that they have the least friction and a much higher intrinsic efficiency than trapezoidal threads.
1296// They produce no radial load on the nut. However, square threads cannot carry as much load as trapezoidal threads.
1297// Arguments:
1298// d = Outer diameter of threaded rod.
1299// l / length / h / height = Length of threaded rod.
1300// pitch = Thread spacing.
1301// ---
1302// left_handed = if true, create left-handed threads. Default = false
1303// starts = The number of lead starts. Default = 1
1304// bevel = if true, bevel the thread ends. Default: false
1305// bevel1 = if true bevel the bottom end.
1306// bevel2 = if true bevel the top end.
1307// internal = If true, this is a mask for making internal threads.
1308// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1309// blunt_start1 = If true apply truncated blunt start threads bottom end.
1310// blunt_start2 = If true apply truncated blunt start threads top end.
1311// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1312// end_len1 = Specify unthreaded length at the bottom
1313// end_len2 = Specify unthreaded length at the top
1314// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1315// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1316// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1317// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1318// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1319// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1320// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1321// teardrop = If true, adds a teardrop profile to the back (Y+) side of the threaded rod, for 3d printability of horizontal holes. If numeric, specifies the proportional extra distance of the teardrop flat top from the screw center, or set to "max" for a pointed teardrop. Default: false
1322// d1 = Bottom outside diameter of threads.
1323// d2 = Top outside diameter of threads.
1324// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1325// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1326// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1327// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1328// Example(2D):
1329// projection(cut=true)
1330// square_threaded_rod(d=10, l=15, pitch=2, orient=BACK);
1331// Examples(Med):
1332// square_threaded_rod(d=10, l=20, pitch=2, starts=2, $fn=32);
1333// Example(Med;VPR=[100,0,5];VPD=220): Masking a Horizontal Threaded Hole
1334// difference() {
1335// cuboid(50);
1336// square_threaded_rod(
1337// d=25, l=51, pitch=4, $fn=36,
1338// internal=true, bevel=true,
1339// blunt_start=false,
1340// teardrop=true, orient=FWD
1341// );
1342// }
1343function square_threaded_rod(
1344 d, l, pitch,
1345 left_handed=false,
1346 bevel,bevel1,bevel2,
1347 starts=1,
1348 internal=false,
1349 d1, d2, length, h, height,
1350 blunt_start, blunt_start1, blunt_start2,
1351 lead_in, lead_in1, lead_in2,
1352 lead_in_ang, lead_in_ang1, lead_in_ang2,
1353 end_len, end_len1, end_len2,
1354 lead_in_shape="default",
1355 teardrop=false,
1356 anchor, spin, orient
1357) = no_function("square_threaded_rod");
1358module square_threaded_rod(
1359 d, l, pitch,
1360 left_handed=false,
1361 bevel,bevel1,bevel2,
1362 starts=1,
1363 internal=false,
1364 d1, d2, length, h, height,
1365 blunt_start, blunt_start1, blunt_start2,
1366 lead_in, lead_in1, lead_in2,
1367 lead_in_ang, lead_in_ang1, lead_in_ang2,
1368 end_len, end_len1, end_len2,
1369 lead_in_shape="default",
1370 teardrop=false,
1371 anchor, spin, orient
1372) {
1373 trapezoidal_threaded_rod(
1374 d=d, l=l, pitch=pitch,
1375 thread_angle=0.1,
1376 left_handed=left_handed,
1377 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
1378 starts=starts,
1379 internal=internal, length=length, height=height, h=h,
1380 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
1381 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
1382 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
1383 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
1384 teardrop=teardrop,
1385 d1=d1, d2=d2,
1386 anchor=anchor,
1387 spin=spin,
1388 orient=orient
1389 ) children();
1390}
1391
1392
1393
1394// Module: square_threaded_nut()
1395// Synopsis: Creates a square-threaded nut.
1396// SynTags: Geom
1397// Topics: Threading, Screws
1398// See Also: square_threaded_rod()
1399// Usage:
1400// square_threaded_nut(nutwidth, id, h|height|thickness, pitch, ...) [ATTACHMENTS];
1401// Description:
1402// Constructs a hexagonal or square nut for a square profile threaded screw rod.
1403// Arguments:
1404// nutwidth = diameter of the nut.
1405// id = inner diameter of threaded hole, measured from bottom of threads
1406// h / height / l / length / thickness = height/thickness of nut.
1407// pitch = Length between threads.
1408// ---
1409// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
1410// left_handed = if true, create left-handed threads. Default = false
1411// starts = The number of lead starts. Default = 1
1412// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
1413// bevel1 = if true, bevel the outside of the nut bottom.
1414// bevel2 = if true, bevel the outside of the nut top.
1415// bevang = set the angle for the outside nut bevel. Default: 30
1416// ibevel = if true, bevel the inside (the hole). Default: true
1417// ibevel1 = if true bevel the inside, bottom end.
1418// ibevel2 = if true bevel the inside, top end.
1419// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1420// blunt_start1 = If true apply truncated blunt start threads bottom end.
1421// blunt_start2 = If true apply truncated blunt start threads top end.
1422// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1423// end_len1 = Specify unthreaded length at the bottom
1424// end_len2 = Specify unthreaded length at the top
1425// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1426// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1427// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1428// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1429// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1430// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1431// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1432// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1433// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1434// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1435// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1436// Examples(Med):
1437// square_threaded_nut(nutwidth=16, id=10, h=10, pitch=2, starts=2, $slop=0.1, $fn=32);
1438function square_threaded_nut(
1439 nutwidth, id, h,
1440 pitch,
1441 left_handed=false,
1442 bevel,bevel1,bevel2,bevang=30,
1443 ibevel,ibevel1,ibevel2,
1444 height,thickness,
1445 length, l,
1446 blunt_start, blunt_start1, blunt_start2,
1447 lead_in, lead_in1, lead_in2,
1448 lead_in_ang, lead_in_ang1, lead_in_ang2,
1449 end_len, end_len1, end_len2,
1450 lead_in_shape="default",
1451 starts=1,
1452 anchor, spin, orient
1453) = no_function("square_threaded_nut");
1454module square_threaded_nut(
1455 nutwidth, id, h,
1456 pitch,
1457 left_handed=false,
1458 bevel,bevel1,bevel2,bevang=30,
1459 ibevel,ibevel1,ibevel2,
1460 height,thickness,
1461 length, l,
1462 blunt_start, blunt_start1, blunt_start2,
1463 lead_in, lead_in1, lead_in2,
1464 lead_in_ang, lead_in_ang1, lead_in_ang2,
1465 end_len, end_len1, end_len2,
1466 lead_in_shape="default",
1467 starts=1,
1468 anchor, spin, orient
1469) {
1470 assert(is_num(pitch) && pitch>=0)
1471 trapezoidal_threaded_nut(
1472 nutwidth=nutwidth, id=id, h=h, pitch=pitch,
1473 thread_angle=0,
1474 left_handed=left_handed,
1475 bevel=bevel,bevel1=bevel1,bevel2=bevel2, bevang=bevang,
1476 ibevel=ibevel, ibevel1=ibevel1, ibevel2=ibevel2,
1477 height=height,thickness=thickness,
1478 starts=starts,
1479 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
1480 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
1481 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
1482 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
1483 l=l,length=length,
1484 anchor=anchor,
1485 spin=spin,
1486 orient=orient
1487 ) children();
1488}
1489
1490
1491// Section: Ball Screws
1492
1493// Module: ball_screw_rod()
1494// Synopsis: Creates a ball screw rod.
1495// SynTags: Geom
1496// Topics: Threading, Screws
1497// Usage:
1498// ball_screw_rod(d, l|length, pitch, [ball_diam], [ball_arc], [internal=], ...) [ATTACHMENTS];
1499// Description:
1500// Constructs a ball screw rod. This type of rod is used with ball bearings.
1501// Arguments:
1502// d = Outer diameter of threaded rod.
1503// l / length / h / height = Length of threaded rod.
1504// pitch = Thread spacing. Also, the diameter of the ball bearings used.
1505// ball_diam = The diameter of the ball bearings to use with this ball screw.
1506// ball_arc = The arc portion that should touch the ball bearings. Default: 120 degrees.
1507// ---
1508// left_handed = if true, create left-handed threads. Default = false
1509// starts = The number of lead starts. Default = 1
1510// bevel = if true, bevel the thread ends. Default: false
1511// bevel1 = if true bevel the bottom end.
1512// bevel2 = if true bevel the top end.
1513// internal = If true, make this a mask for making internal threads.
1514// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1515// blunt_start1 = If true apply truncated blunt start threads bottom end.
1516// blunt_start2 = If true apply truncated blunt start threads top end.
1517// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1518// end_len1 = Specify unthreaded length at the bottom
1519// end_len2 = Specify unthreaded length at the top
1520// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1521// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1522// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1523// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1524// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1525// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1526// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1527// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1528// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1529// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1530// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1531// Example(2D): Thread Profile, ball_diam=4, ball_arc=100
1532// projection(cut=true) ball_screw_rod(d=10, l=15, pitch=5, ball_diam=4, ball_arc=100, orient=BACK, $fn=24, blunt_start=false);
1533// Example(2D): Thread Profile, ball_diam=4, ball_arc=120
1534// projection(cut=true) ball_screw_rod(d=10, l=15, pitch=5, ball_diam=4, ball_arc=120, orient=BACK, $fn=24, blunt_start=false);
1535// Example(2D): Thread Profile, ball_diam=3, ball_arc=120
1536// projection(cut=true) ball_screw_rod(d=10, l=15, pitch=5, ball_diam=3, ball_arc=120, orient=BACK, $fn=24, blunt_start=false);
1537// Examples(Med):
1538// ball_screw_rod(d=15, l=20, pitch=8, ball_diam=5, ball_arc=120, $fa=1, $fs=0.5, blunt_start=false);
1539// ball_screw_rod(d=15, l=20, pitch=5, ball_diam=4, ball_arc=120, $fa=1, $fs=0.5, blunt_start=false);
1540// ball_screw_rod(d=15, l=20, pitch=5, ball_diam=4, ball_arc=120, left_handed=true, $fa=1, $fs=0.5, blunt_start=false);
1541function ball_screw_rod(
1542 d, l, pitch,
1543 ball_diam=5, ball_arc=100,
1544 starts=1,
1545 left_handed=false,
1546 internal=false,
1547 length, h, height,
1548 bevel, bevel1, bevel2,
1549 blunt_start, blunt_start1, blunt_start2,
1550 lead_in, lead_in1, lead_in2,
1551 lead_in_ang, lead_in_ang1, lead_in_ang2,
1552 end_len, end_len1, end_len2,
1553 lead_in_shape="default",
1554 anchor, spin, orient
1555) = no_function("ball_screw_rod");
1556module ball_screw_rod(
1557 d, l, pitch,
1558 ball_diam=5, ball_arc=100,
1559 starts=1,
1560 left_handed=false,
1561 internal=false,
1562 length, h, height,
1563 bevel, bevel1, bevel2,
1564 blunt_start, blunt_start1, blunt_start2,
1565 lead_in, lead_in1, lead_in2,
1566 lead_in_ang, lead_in_ang1, lead_in_ang2,
1567 end_len, end_len1, end_len2,
1568 lead_in_shape="default",
1569 anchor, spin, orient
1570) {
1571 n = max(3,ceil(segs(ball_diam/2)*ball_arc/2/360));
1572 depth = ball_diam * (1-cos(ball_arc/2))/2;
1573 cpy = ball_diam/2/pitch*cos(ball_arc/2);
1574 profile = [
1575 each arc(n=n, d=ball_diam/pitch, cp=[-0.5,cpy], start=270, angle=ball_arc/2),
1576 each arc(n=n, d=ball_diam/pitch, cp=[+0.5,cpy], start=270-ball_arc/2, angle=ball_arc/2)
1577 ];
1578 generic_threaded_rod(
1579 d=d, l=l, pitch=pitch,
1580 profile=profile,
1581 left_handed=left_handed,
1582 starts=starts,
1583 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
1584 internal=internal, length=length, height=height, h=h,
1585 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
1586 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
1587 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
1588 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
1589 anchor=anchor,
1590 spin=spin,
1591 orient=orient
1592 ) children();
1593}
1594
1595
1596// Section: Generic Threading
1597
1598// Module: generic_threaded_rod()
1599// Synopsis: Creates a generic threaded rod.
1600// SynTags: Geom
1601// Topics: Threading, Screws
1602// See Also: generic_threaded_nut()
1603// Usage:
1604// generic_threaded_rod(d, l|length, pitch, profile, [internal=], ...) [ATTACHMENTS];
1605// Description:
1606// Constructs a generic threaded rod using an arbitrary thread profile that you supply. The rod can be tapered
1607// (e.g. for pipe threads). For specific thread types use other modules that supply the appropriate profile.
1608// .
1609// You give the profile as a 2D path that will be scaled by the pitch to produce the final thread shape. The profile
1610// X values must be between -1/2 and 1/2. The Y=0 point will align with the specified rod diameter, so generally you
1611// want a Y value of zero at the peak (which makes your specified diameter the outer diameter of the threads). The
1612// value in the valleys of the thread should then be `-depth/pitch` due to the scaling by the thread pitch. The first
1613// and last points should generally have the same Y value, but it is not necessary to give values at X=1/2 or X=-1/2
1614// if unless the Y values differ from the interior points in the profile. Generally you should center the profile
1615// horizontally in the interval [-1/2, 1/2].
1616// .
1617// If internal is true then produce a thread mask to difference from an object. When internal is true the rod
1618// diameter is enlarged to correct for the polygonal nature of circles to ensure that the internal diameter is the
1619// specified size. The diameter is also increased by `4 * $slop` to create clearance for threading by allowing a `2 *
1620// $slop` gap on each side. If bevel is set to true and internal is false then the ends of the rod will be beveled.
1621// When bevel is true and internal is true the ends of the rod will be filled in so that the rod mask will create a
1622// bevel when subtracted from an object. The bevel is at 45 deg and is the depth of the threads.
1623// .
1624// Blunt start threading, which is the default, specifies that the thread ends abruptly at its full width instead of
1625// running off the end of the shaft and leaving a sharp edged partial thread at the end of the screw. This makes
1626// screws easier to start and prevents cross threading. Blunt start threads should always be superior, and they are
1627// faster to model, but if you really need standard threads that run off the end you can set `blunt_start=false`.
1628// .
1629// The teardrop option cuts off the threads with a teardrop for 3d printability of horizontal holes. By default,
1630// if the screw outer radius is r then the flat top will be at distance 1.05r from the center, adding a 5% space.
1631// You can set teardrop to a numerical value to adjust that percentage, e.g. a value of 0.1 would give a 10% space.
1632// You can set teardrop to "max" to create a pointy-top teardrop with no flat section.
1633// Arguments:
1634// d = Outer diameter of threaded rod.
1635// l / length / h / height = Length of threaded rod.
1636// pitch = Thread spacing.
1637// profile = A 2D path giving the shape of a thread
1638// ---
1639// left_handed = If true, create left-handed threads. Default: false
1640// starts = The number of lead starts. Default: 1
1641// internal = If true, make this a mask for making internal threads. Default: false
1642// d1 = Bottom outside diameter of threads.
1643// d2 = Top outside diameter of threads.
1644// bevel = set to true to bevel both ends, a number to specify a bevel size, false for no bevel, and "reverse" for an inverted bevel
1645// bevel1 = set bevel for bottom end.
1646// bevel2 = set bevel for top end.
1647// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1648// blunt_start1 = If true apply truncated blunt start threads bottom end.
1649// blunt_start2 = If true apply truncated blunt start threads top end.
1650// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1651// end_len1 = Specify unthreaded length at the bottom
1652// end_len2 = Specify unthreaded length at the top
1653// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1654// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1655// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1656// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1657// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1658// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1659// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1660// teardrop = If true, adds a teardrop profile to the back (Y+) side of the threaded rod, for 3d printability of horizontal holes. If numeric, specifies the proportional extra distance of the teardrop flat top from the screw center, or set to "max" for a pointed teardrop (see above). Default: false
1661// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1662// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1663// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1664// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1665// Example(2DMed): Example Tooth Profile
1666// pitch = 2;
1667// depth = pitch * cos(30) * 5/8;
1668// profile = [
1669// [-7/16, -depth/pitch*1.07],
1670// [-6/16, -depth/pitch],
1671// [-1/16, 0],
1672// [ 1/16, 0],
1673// [ 6/16, -depth/pitch],
1674// [ 7/16, -depth/pitch*1.07]
1675// ];
1676// stroke(profile, width=0.02);
1677// Example:
1678// pitch = 2;
1679// depth = pitch * cos(30) * 5/8;
1680// profile = [
1681// [-7/16, -depth/pitch*1.07],
1682// [-6/16, -depth/pitch],
1683// [-1/16, 0],
1684// [ 1/16, 0],
1685// [ 6/16, -depth/pitch],
1686// [ 7/16, -depth/pitch*1.07]
1687// ];
1688// generic_threaded_rod(d=10, l=40, pitch=2, profile=profile);
1689
1690function generic_threaded_rod(
1691 d, l, pitch, profile,
1692 left_handed=false, internal=false,
1693 bevel, bevel1, bevel2,
1694 starts=1,
1695 d1, d2, length, h, height,
1696 blunt_start, blunt_start1, blunt_start2,
1697 lead_in, lead_in1, lead_in2,
1698 lead_in_ang, lead_in_ang1, lead_in_ang2,
1699 end_len, end_len1, end_len2,
1700 lead_in_shape="default",
1701 teardrop=false,
1702 anchor, spin, orient
1703) = no_function("generic_threaded_rod");
1704module generic_threaded_rod(
1705 d, l, pitch, profile,
1706 left_handed=false, internal=false,
1707 bevel, bevel1, bevel2,
1708 starts=1,
1709 d1, d2, length, h, height,
1710 blunt_start, blunt_start1, blunt_start2,
1711 lead_in, lead_in1, lead_in2,
1712 lead_in_ang, lead_in_ang1, lead_in_ang2,
1713 end_len, end_len1, end_len2,
1714 lead_in_shape="default",
1715 teardrop=false,
1716 anchor, spin, orient
1717) {
1718 len = one_defined([l,length,h,height],"l,length,h,height");
1719 bevel1 = first_defined([bevel1,bevel]);
1720 bevel2 = first_defined([bevel2,bevel]);
1721 blunt_start1 = first_defined([blunt_start1, blunt_start, true]);
1722 blunt_start2 = first_defined([blunt_start2, blunt_start, true]);
1723 r1 = get_radius(d1=d1, d=d);
1724 r2 = get_radius(d1=d2, d=d);
1725 lead_in1 = first_defined([lead_in1, lead_in]);
1726 lead_in2 = first_defined([lead_in2, lead_in]);
1727 lead_in_func = is_func(lead_in_shape) ? lead_in_shape
1728 : assert(is_string(lead_in_shape),"lead_in_shape must be a function or string")
1729 let(ind = search([lead_in_shape], _lead_in_table,0)[0])
1730 assert(ind!=[],str("Unknown lead_in_shape, \"",lead_in_shape,"\""))
1731 _lead_in_table[ind[0]][1];
1732 dummy0 =
1733 assert(all_positive([pitch]),"Thread pitch must be a positive value")
1734 assert(all_positive([len]),"Length must be a postive value")
1735 assert(is_path(profile),"Profile must be a path")
1736 assert(is_bool(blunt_start1), "blunt_start1/blunt_start must be boolean")
1737 assert(is_bool(blunt_start2), "blunt_start2/blunt_start must be boolean")
1738 assert(is_bool(left_handed))
1739 assert(all_positive([r1,r2]), "Must give d or both d1 and d2 as positive values")
1740 assert(is_undef(bevel1) || is_num(bevel1) || is_bool(bevel1) || bevel1=="reverse", "bevel1/bevel must be a number, boolean or \"reverse\"")
1741 assert(is_undef(bevel2) || is_num(bevel2) || is_bool(bevel2) || bevel2=="reverse", "bevel2/bevel must be a number, boolean or \"reverse\"");
1742 sides = quantup(segs(max(r1,r2)), starts);
1743 rsc = internal? (1/cos(180/sides)) : 1; // Internal radius adjusted for faceting
1744 islop = internal? 2*get_slop() : 0;
1745 r1adj = r1 * rsc + islop;
1746 r2adj = r2 * rsc + islop;
1747
1748 extreme = internal? max(column(profile,1)) : min(column(profile,1));
1749 profile = !internal ? profile
1750 : let(
1751 maxidx = [for(i=idx(profile)) if (profile[i].y==extreme) i],
1752 cutpt = len(maxidx)==1 ? profile(maxidx[0]).x
1753 : mean([profile[maxidx[0]].x, profile[maxidx[1]].x])
1754 )
1755 [
1756 for(entry=profile) if (entry.x>=cutpt) [entry.x-cutpt-1/2,entry.y],
1757 for(entry=profile) if (entry.x<cutpt) [entry.x-cutpt+1/2,entry.y]
1758 ];
1759 profmin = pitch * min(column(profile,1));
1760 pmax = pitch * max(column(profile,1));
1761 rmax = max(r1adj,r2adj)+pmax;
1762
1763 // These parameters give the size of the bevel, negative for an outward bevel (e.g. on internal thread mask)
1764 bev1 = (bevel1=="reverse"?-1:1)*(internal?-1:1) *
1765 ( is_num(bevel1)? bevel1
1766 : bevel1==false? 0
1767 : blunt_start1? (bevel1==undef?0
1768 :internal ? r1/6
1769 :(r1+profmin)/6)
1770 : pmax-profmin);
1771 bev2 = (bevel2=="reverse"?-1:1)*(internal?-1:1) *
1772 ( is_num(bevel2)? bevel2
1773 : bevel2==false? 0
1774 : blunt_start2? (bevel2==undef?0
1775 :internal ? r2/6
1776 :(r2+profmin)/6)
1777 : pmax-profmin);
1778 // This is the bevel size used for constructing the polyhedron. The bevel is integrated when blunt start is on, but
1779 // applied later via difference/union if blunt start is off, so set bevel to zero in the latter case.
1780 bevel_size1 = blunt_start1?bev1:0;
1781 bevel_size2 = blunt_start2?bev2:0;
1782 // This is the bevel size for clipping, which is only done when blunt start is off
1783 clip_bev1 = blunt_start1?0:bev1;
1784 clip_bev2 = blunt_start2?0:bev2;
1785 end_len1_base = !blunt_start1? 0 : first_defined([end_len1,end_len, 0]);
1786 end_len2_base = !blunt_start2? 0 : first_defined([end_len2,end_len, 0]);
1787 // Enlarge end lengths to give sufficient room for requested bevel
1788 end_len1 = abs(bevel_size1)>0 ? max(end_len1_base, abs(bevel_size1)) : end_len1_base;
1789 end_len2 = abs(bevel_size2)>0 ? max(end_len2_base, abs(bevel_size2)) : end_len2_base;
1790 // length to create below/above z=0, with an extra revolution in non-blunt-start case so
1791 // the threads can continue to the specified length and we can clip off the blunt start
1792 len1 = -len/2 - (blunt_start1?0:pitch);
1793 len2 = len/2 + (blunt_start2?0:pitch);
1794
1795 // Thread turns below and above z=0, with extra to ensure we go beyond the length needed
1796 turns1 = len1/pitch-1;
1797 turns2 = len2/pitch+1;
1798 dir = left_handed? -1 : 1;
1799 dummy2=
1800 assert(abs(bevel_size1)+abs(bevel_size2)<len, "Combined bevel size exceeds length of screw")
1801 assert(r1adj+extreme*pitch-bevel_size1>0, "bevel1 is too large to fit screw diameter")
1802 assert(r2adj+extreme*pitch-bevel_size2>0, "bevel2 is too large to fit screw diameter");
1803
1804 margin1 = profile[0].y==extreme ? profile[0].x : -1/2;
1805 margin2 = last(profile).y==extreme? last(profile).x : 1/2;
1806 lead_in_default = pmax-profmin;//2*pitch;
1807 // 0*360/10;// /4/32*360; higlen_default;//0*4/32*360; //2/32*360;//360*max(pitch/2, pmax-depth)/(2*PI*r2adj);
1808 // lead_in length needs to be quantized to match the samples
1809 lead_in_ang1 = !blunt_start1? 0 :
1810 let(
1811 user_ang = first_defined([lead_in_ang1,lead_in_ang])
1812 )
1813 assert(is_undef(user_ang) || is_undef(lead_in1), "Cannot define lead_in/lead_in1 by both length and angle")
1814 quantup(
1815 is_def(user_ang) ? user_ang : default(lead_in1, lead_in_default)*360/(2*PI*r1adj)
1816 , 360/sides);
1817 lead_in_ang2 = !blunt_start2? 0 :
1818 let(
1819 user_ang = first_defined([lead_in_ang2,lead_in_ang])
1820 )
1821 assert(is_undef(user_ang) || is_undef(lead_in2), "Cannot define lead_in/lead_in2 by both length and angle")
1822 quantup(
1823 is_def(user_ang) ? user_ang : default(lead_in2, lead_in_default)*360/(2*PI*r2adj)
1824 , 360/sides);
1825 // cut_ang also need to be quantized, but the comparison is offset by 36*turns1/starts, so we need to pull that factor out
1826 // of the quantization. (The loop over angle starts at 360*turns1/starts, not at a multiple of 360/sides.)
1827// cut_ang1 = 360 * (len1/pitch-margin1+end_len1/pitch) / starts + lead_in_ang1;
1828// cut_ang2 = 360 * (len2/pitch-margin2-end_len2/pitch) / starts - lead_in_ang2;
1829 cut_ang1 = quantup(360 * (len1/pitch-margin1+end_len1/pitch) / starts + lead_in_ang1-360*turns1/starts,360/sides)+360*turns1/starts;
1830 cut_ang2 = quantdn(360 * (len2/pitch-margin2-end_len2/pitch) / starts - lead_in_ang2-360*turns1/starts,360/sides)+360*turns1/starts;
1831 dummy1 =
1832 assert(cut_ang1<cut_ang2, "lead in length are too long for the amount of thread: they overlap")
1833 assert(is_num(lead_in_ang1), "lead_in1/lead_in must be a number")
1834 assert(r1adj+profmin>0 && r2adj+profmin>0, "Screw profile deeper than rod radius");
1835 map_threads = right((r1adj + r2adj) / 2) // Shift profile out to thread radius
1836 * affine3d_skew(sxz=(r2adj-r1adj)/len) // Skew correction for tapered threads
1837 * frame_map(x=[0,0,1], y=[1,0,0]) // Map profile to 3d, parallel to z axis
1838 * scale(pitch); // scale profile by pitch
1839 start_steps = sides / starts;
1840
1841 // This is the location for clipping the polyhedron, below the bevel, if one is present, or at length otherwise
1842 // Clipping is done before scaling to pitch, so we need to divide by the pitch
1843 rod_clip1 = (len1+abs(bevel_size1))/pitch;
1844 rod_clip2 = (len2-abs(bevel_size2))/pitch;
1845 prof3d=path3d(profile,1);
1846 thread_verts = [
1847 // Outer loop constructs a vertical column of the screw at each angle
1848 // covering 360/starts degrees of the cylinder.
1849 for (step = [0:1:start_steps])
1850 let(
1851 ang = 360 * step/sides,
1852 dz = step / start_steps, // z offset for threads at this angle
1853 rot_prof = zrot(ang*dir)*map_threads, // Rotate profile to correct angular location
1854 full_profile = [ // profile for the entire rod
1855 for (turns = [turns1:1:turns2])
1856 let(
1857 tang = turns/starts * 360 + ang,
1858 // EPSILON offset prevents funny looking extensions of the thread from its very tip
1859 // by forcing values near the tip to evaluate as less than zero = beyond the tip end
1860 hsc = tang < cut_ang1 ? lead_in_func(-EPSILON+1-(cut_ang1-tang)/lead_in_ang1,PI*2*r1adj*lead_in_ang1/360 )
1861 : tang > cut_ang2 ? lead_in_func(-EPSILON+1-(tang-cut_ang2)/lead_in_ang2,PI*2*r2adj*lead_in_ang2/360 )
1862 : [1,1],
1863 shift_and_scale = [[hsc.x, 0], [0,hsc.y], [dz+turns,(1-hsc.y)*extreme]]
1864 )
1865 // This is equivalent to apply(right(dz+turns)*higscale, profile)
1866 //
1867 // The right movement finds the position of the thread along
1868 // what will be the z axis after the profile is mapped to 3d,
1869 // and higscale creates a taper and the end of the threads.
1870 each prof3d*shift_and_scale
1871 ],
1872 // Clip profile at the ends of the rod and add a z coordinate
1873 full_profile_clipped = [
1874 for(pts=full_profile) [max(rod_clip1,min(rod_clip2,pts.x)), pts.y, 0]
1875 ]
1876 )
1877 [
1878 [0,0,len1],
1879 //if (true) apply(rot_prof, [len1/pitch,extreme+2/pitch ,0]),
1880 if (bevel_size1) apply(rot_prof, [len1/pitch,extreme-bevel_size1/pitch ,0]),
1881 each apply(rot_prof, full_profile_clipped),
1882 if (bevel_size2) apply(rot_prof, [len2/pitch,extreme-bevel_size2/pitch ,0]),
1883 //if (true) apply(rot_prof, [len2/pitch,extreme+2/pitch ,0]),
1884 [0, 0, len2]
1885 ]
1886 ];
1887 style=internal?"concave":"convex";
1888 thread_vnf = vnf_join([
1889 for (i=[0:1:starts-1])
1890 zrot(i*360/starts, p=vnf_vertex_array(thread_verts, reverse=left_handed, style=style,col_wrap=false)),
1891 ]);
1892 slope = (r1adj-r2adj)/len;
1893 dummy3 =
1894 assert(r1adj+pmax-clip_bev1>0, "bevel1 is too large to fit screw diameter")
1895 assert(r2adj+pmax-clip_bev2>0, "bevel2 is too large to fit screw diameter")
1896 assert(abs(clip_bev1)+abs(clip_bev2)<len, "Combined bevel size exceeds length of screw");
1897 attachable(anchor,spin,orient, r1=r1adj, r2=r2adj, l=len) {
1898 union(){
1899 difference() {
1900 vnf_polyhedron(thread_vnf,convexity=10);
1901 if (clip_bev1>0)
1902 rotate_extrude()
1903 polygon([[ 0,-len/2],
1904 [r1adj+pmax-clip_bev1 ,-len/2],
1905 [r1adj+pmax-slope*clip_bev1,-len/2+clip_bev1],
1906 [ rmax+1,-len/2+clip_bev1],
1907 [ rmax+1, len1-1],
1908 [ 0, len1-1]]);
1909 if (clip_bev2>0)
1910 rotate_extrude()
1911 polygon([[ 0, len/2],
1912 [r2adj+pmax-clip_bev2 , len/2],
1913 [r2adj+pmax+slope*clip_bev2, len/2-clip_bev2],
1914 [ rmax+1, len/2-clip_bev2],
1915 [ rmax+1, len2+1],
1916 [ 0, len2+1]]);
1917 if (!blunt_start1 && clip_bev1<=0)
1918 down(len/2) cuboid([2*rmax+1,2*rmax+1, -len1+1], anchor=TOP);
1919 if (!blunt_start2 && clip_bev2<=0)
1920 up(len/2) cuboid([2*rmax+1,2*rmax+1, len2+1], anchor=BOTTOM);
1921 }
1922
1923 // Add bevel for internal thread mask
1924 if (clip_bev1<0)
1925 down(len/2+.001)cyl(l=-clip_bev1, r2=r1adj+profmin, r1=r1adj+profmin+slope*clip_bev1-clip_bev1,anchor=BOTTOM);
1926 if (clip_bev2<0)
1927 up(len/2+.001)cyl(l=-clip_bev2, r1=r2adj+profmin, r2=r2adj+profmin+slope*clip_bev1-clip_bev2,anchor=TOP);
1928
1929 // Add teardrop profile
1930 if (teardrop!=false) {
1931 fact = is_num(teardrop) ? assert(teardrop>=0,"teardrop value cannot be negative")1-1/sqrt(2)+teardrop
1932 : is_bool(teardrop) ? 1-1/sqrt(2)+0.05
1933 : teardrop=="max" ? 1/sqrt(2)
1934 : assert(false,"invalid teardrop value");
1935 dummy = assert(fact<=1/sqrt(2), "teardrop value too large");
1936 pdepth = pmax-profmin;
1937 trap1 = back((r1adj+pmax)/sqrt(2),path3d(list_rotate(trapezoid(ang=45,w1 = (r1adj+pmax)*sqrt(2), h = (r1adj+pmax)*fact,anchor=FWD),1),-l/2));
1938 trap2 = back((r2adj+pmax)/sqrt(2),path3d(list_rotate(trapezoid(ang=45,w1 = (r2adj+pmax)*sqrt(2), h = (r2adj+pmax)*fact,anchor=FWD),1), l/2));
1939 yproj = [[1,0,0],[0,0,0],[0,0,1]];
1940 p1a=trap1[0]+unit([0,0,-l/2]-trap1[0])*pdepth*3/4;
1941 p1b=last(trap1)+unit([0,0,-l/2]-last(trap1))*pdepth*3/4;
1942 p2a=trap2[0]+unit([0,0,l/2]-trap2[0])*pdepth*3/4;
1943 p2b=last(trap2)+ unit([0,0,l/2]-last(trap2))*pdepth*3/4 ;
1944 cut1 = reverse([p1a, p1a*yproj, p1b*yproj, p1b]);
1945 cut2 = reverse([p2a, p2a*yproj, p2b*yproj, p2b]);
1946 vert = [
1947 [each cut1, each trap1],
1948 [each cut2, each trap2]
1949 ];
1950 vnf_polyhedron(vnf_vertex_array(vert,caps=true,col_wrap=true));
1951 // Old code creates an internal teardrop which unfortunately doesn't print well
1952 //ang = min(45,opp_hyp_to_ang(rmax+profmin, rmax+pmax));
1953 //xrot(-90) teardrop(l=l, r1=r1adj+profmin, r2=r2adj+profmin, ang=ang, cap_h1=r1adj+pmax, cap_h2=r2adj+pmax);
1954 }
1955 }
1956 children();
1957 }
1958}
1959
1960
1961
1962// Module: generic_threaded_nut()
1963// Synopsis: Creates a generic threaded nut.
1964// SynTags: Geom
1965// Topics: Threading, Screws
1966// See Also: generic_threaded_rod()
1967// Usage:
1968// generic_threaded_nut(nutwidth, id, h|height|thickness, pitch, profile, [$slop], ...) [ATTACHMENTS];
1969// Description:
1970// Constructs a hexagonal or square nut for an generic threaded rod using a user-supplied thread profile.
1971// See {{generic_threaded_rod()}} for details on the profile specification.
1972// Arguments:
1973// nutwidth = outer dimension of nut from flat to flat.
1974// id = inner diameter of threaded hole, measured from bottom of threads
1975// h / height / thickness = height/thickness of nut.
1976// pitch = Thread spacing.
1977// profile = Thread profile.
1978// ---
1979// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
1980// left_handed = if true, create left-handed threads. Default = false
1981// starts = The number of lead starts. Default = 1
1982// id1 = inner diameter at the bottom
1983// id2 = inner diameter at the top
1984// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
1985// bevel1 = if true, bevel the outside of the nut bottom.
1986// bevel2 = if true, bevel the outside of the nut top.
1987// bevang = set the angle for the outside nut bevel. Default: 30
1988// ibevel = if true, bevel the inside (the hole). Default: true
1989// ibevel1 = if true bevel the inside, bottom end.
1990// ibevel2 = if true bevel the inside, top end.
1991// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1992// blunt_start1 = If true apply truncated blunt start threads bottom end.
1993// blunt_start2 = If true apply truncated blunt start threads top end.
1994// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1995// end_len1 = Specify unthreaded length at the bottom
1996// end_len2 = Specify unthreaded length at the top
1997// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1998// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1999// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
2000// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
2001// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
2002// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
2003// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
2004// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
2005// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
2006// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
2007// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
2008function generic_threaded_nut(
2009 nutwidth,
2010 id,
2011 h,
2012 pitch,
2013 profile,
2014 shape="hex",
2015 left_handed=false,
2016 starts=1,
2017 bevel,bevel1,bevel2,bevang=30,
2018 ibevel, ibevel1, ibevel2,
2019 id1,id2, height, thickness,
2020 length, l,
2021 blunt_start, blunt_start1, blunt_start2,
2022 lead_in, lead_in1, lead_in2,
2023 lead_in_ang, lead_in_ang1, lead_in_ang2,
2024 end_len, end_len1, end_len2,
2025 lead_in_shape="default",
2026 anchor, spin, orient
2027) = no_function("generic_threaded_nut");
2028module generic_threaded_nut(
2029 nutwidth,
2030 id,
2031 h,
2032 pitch,
2033 profile,
2034 shape="hex",
2035 left_handed=false,
2036 starts=1,
2037 bevel,bevel1,bevel2,bevang=30,
2038 ibevel, ibevel1, ibevel2,
2039 id1,id2, height, thickness,
2040 length, l,
2041 blunt_start, blunt_start1, blunt_start2,
2042 lead_in, lead_in1, lead_in2,
2043 lead_in_ang, lead_in_ang1, lead_in_ang2,
2044 end_len, end_len1, end_len2,
2045 lead_in_shape="default",
2046 anchor, spin, orient
2047) {
2048
2049 extra = 0.01;
2050 id1 = first_defined([id1,id]);
2051 id2 = first_defined([id2,id]);
2052 h = one_defined([h,height,thickness,l,length],"h,height,thickness,l,length");
2053 dummyA = assert(is_num(pitch) && pitch>=0, "pitch must be a nonnegative number")
2054 assert(is_num(h) && h>0, "height/thickness must be a positive number")
2055 assert(in_list(shape,["square","hex"]), "shape must be \"hex\" or \"square\"")
2056 assert(all_positive([id1,id2]), "Inner diameter(s) of nut must be positive number(s)");
2057 slope = (id2-id1)/h;
2058 full_id1 = id1-slope*extra/2;
2059 full_id2 = id2+slope*extra/2;
2060 ibevel1 = first_defined([ibevel1,ibevel,true]);
2061 ibevel2 = first_defined([ibevel2,ibevel,true]);
2062 bevel1 = first_defined([bevel1,bevel,shape=="hex"?true:false]);
2063 bevel2 = first_defined([bevel2,bevel,shape=="hex"?true:false]);
2064 depth = -pitch*min(column(profile,1));
2065 IBEV=0.05;
2066 vnf = linear_sweep(hexagon(id=nutwidth), height=h, center=true);
2067 attachable(anchor,spin,orient, size=shape=="square" ? [nutwidth,nutwidth,h] : undef, vnf=shape=="hex" ? vnf : undef) {
2068 difference() {
2069 _nutshape(nutwidth,h, shape,bevel1,bevel2);
2070 if (pitch==0)
2071 cyl(l=h+extra, d1=full_id1+4*get_slop(), d2=full_id2+4*get_slop(),
2072 chamfer1=ibevel1?-IBEV*full_id1:undef,
2073 chamfer2=ibevel2?-IBEV*full_id2:undef);
2074 else
2075 generic_threaded_rod(
2076 d1=full_id1,d2=full_id2,
2077 l=h+extra,
2078 pitch=pitch,
2079 profile=profile,
2080 left_handed=left_handed,
2081 starts=starts,
2082 internal=true,
2083 bevel1=ibevel1,bevel2=ibevel2,
2084 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
2085 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
2086 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
2087 end_len=end_len, end_len1=end_len1, end_len2=end_len2
2088 );
2089 }
2090 children();
2091 }
2092}
2093
2094
2095module _nutshape(nutwidth, h, shape, bevel1, bevel2)
2096{
2097 bevel_d=0.9;
2098 intersection(){
2099 if (shape=="hex")
2100 cyl(d=nutwidth, circum=true, $fn=6, l=h, chamfer1=bevel1?0:nutwidth*.01, chamfer2=bevel2?0:nutwidth*.01);
2101 else
2102 cuboid([nutwidth,nutwidth,h],chamfer=nutwidth*.01, except=[if (bevel1) BOT, if(bevel2) TOP]);
2103 fn = quantup(segs(r=nutwidth/2),shape=="hex"?6:4);
2104 d = shape=="hex" ? 2*nutwidth/sqrt(3) : sqrt(2)*nutwidth;
2105 chamfsize = (d-nutwidth)/2/bevel_d;
2106 cyl(d=d*.99,h=h+.01,realign=true,circum=true,$fn=fn,chamfer1=bevel1?chamfsize:0,chamfer2=bevel2?chamfsize:0,chamfang=30);
2107 }
2108}
2109
2110
2111// Module: thread_helix()
2112// Synopsis: Creates a thread helix to add to a cylinder.
2113// SynTags: Geom
2114// Topics: Threading, Screws
2115// See Also: generic_threaded_rod()
2116// Usage:
2117// thread_helix(d, pitch, turns=, [thread_depth=], [thread_angle=|flank_angle=], [profile=], [starts=], [internal=], ...) {ATTACHMENTS};
2118// thread_helix(d1=,d2=, pitch=, turns=, [thread_depth=], [thread_angle=|flank_angle=], [profile=], [starts=], [internal=], ...) {ATTACHMENTS};
2119// Description:
2120// Creates a right-handed helical thread with optional end tapering. Unlike
2121// {{generic_threaded_rod()}, this module just generates the thread, and you specify the total
2122// angle of threading that you want, which makes it easy to put complete threads onto a longer
2123// shaft. It also optionally makes a finely divided taper at the thread ends. However, it takes
2124// 2-3 times as long to render compared to {{generic_threaded_rod()}}. This module was designed
2125// to handle threads found in plastic and glass bottles.
2126// .
2127// You can specify a thread_depth and flank_angle, in which case you get a symmetric trapezoidal
2128// thread, whose inner diameter (the base of the threads for external threading) is d (so the
2129// total diameter will be d + thread_depth). This differs from the threaded_rod modules, where
2130// the specified diameter is the outer diameter. Alternatively you can give a profile, following
2131// the same rules as for general_threaded_rod. The Y=0 point will align with the specified
2132// diameter, and the profile should range in X from -1/2 to 1/2. You cannot specify both the
2133// profile and the thread_depth or flank_angle.
2134// .
2135// Unlike {{generic_threaded_rod()}, when internal=true this module generates the threads, not a thread mask.
2136// The profile needs to be inverted to produce the proper thread form. If you use the built-in trapezoidal
2137// thread you get the inverted thread, designed so that the inner diameter is d. If you supply a custom profile
2138// you must invert it yourself to get internal threads. With adequate clearance
2139// this thread will mate with the thread that uses the same parameters but has internal=false. Note that
2140// unlike the threaded_rod modules, thread_helix does not adjust the diameter for faceting, nor does it
2141// subtract any $slop for clearance.
2142// .
2143// The lead_in options specify a lead-in section where the ends of the threads scale down to avoid a sharp face at the thread ends.
2144// You can specify the length of this scaling directly with the lead_in parameters or as an angle using the lead_in_ang parameters.
2145// If you give a positive value, the extrusion is lengthenend by the specified distance or angle; if you give a negative
2146// value then the scaled end is included in the extrusion length specified by `turns`. If the value is zero then no scaled ends
2147// are produced. The shape of the scaled ends can be controlled with the lead_in_shape parameter. Supported options are "sqrt", "linear"
2148// "smooth" and "cut". Lead-in works on both internal and external threads.
2149// Figure(2D,Med,NoAxes):
2150// pa_delta = tan(15)/4;
2151// rr1 = -1/2;
2152// z1 = 1/4-pa_delta;
2153// z2 = 1/4+pa_delta;
2154// profile = [
2155// [-z2, rr1],
2156// [-z1, 0],
2157// [ z1, 0],
2158// [ z2, rr1],
2159// ];
2160// fullprofile = 50*left(1/2,p=concat(profile, right(1, p=profile)));
2161// stroke(fullprofile,width=1);
2162// dir = fullprofile[2]-fullprofile[3];
2163// dir2 = fullprofile[5]-fullprofile[4];
2164// curve = arc(15,angle=[75,87],r=40 /*67.5*/);
2165// avgpt = mean([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2]);
2166// color("red"){
2167// stroke([fullprofile[4]+[0,1], fullprofile[4]+[0,37]], width=1);
2168// stroke([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2], width=1);
2169// stroke(move(-curve[0]+avgpt,p=curve), width=0.71,endcaps="arrow2");
2170// right(14)back(19)text("flank",size=4,halign="center");
2171// right(14)back(14)text("angle",size=4,halign="center");
2172// }
2173// Figure(2D,Med,NoAxes):
2174// pa_delta = tan(15)/4;
2175// rr1 = -1/2;
2176// z1 = 1/4-pa_delta;
2177// z2 = 1/4+pa_delta;
2178// profile = [
2179// [-z2, rr1],
2180// [-z1, 0],
2181// [ z1, 0],
2182// [ z2, rr1],
2183// ];
2184// fullprofile = 50*left(1/2,p=concat(profile, right(1, p=profile)));
2185// stroke(fullprofile,width=1);
2186// dir = fullprofile[2]-fullprofile[3];
2187// dir2 = fullprofile[5]-fullprofile[4];
2188// curve = arc(32,angle=[75,105],r=67.5);
2189// avgpt = mean([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2]);
2190// color("red"){
2191// stroke([fullprofile[2]+.1*dir, fullprofile[2]+.4*dir], width=1);
2192// stroke([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2], width=1);
2193// stroke(move(-curve[0]+avgpt,p=curve), width=1,endcaps="arrow2");
2194// back(10)text("thread",size=4,halign="center");
2195// back(3)text("angle",size=4,halign="center");
2196// }
2197// Arguments:
2198// d = Base diameter of threads. Default: 10
2199// pitch = Distance between threads. Default: 2
2200// ---
2201// turns = Number of revolutions to rotate thread around.
2202// thread_depth = Depth of threads from top to bottom.
2203// flank_angle = Angle of thread faces to plane perpendicular to screw. Default: 15 degrees.
2204// thread_angle = Angle between two thread faces.
2205// profile = If an asymmetrical thread profile is needed, it can be specified here.
2206// starts = The number of thread starts. Default: 1
2207// left_handed = If true, thread has a left-handed winding.
2208// internal = if true make internal threads. The only effect this has is to change how the thread lead_in is constructed. When true, the lead-in section tapers towards the outside; when false, it tapers towards the inside. Default: false
2209// d1 = Bottom inside base diameter of threads.
2210// d2 = Top inside base diameter of threads.
2211// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
2212// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
2213// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
2214// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
2215// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
2216// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
2217// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "sqrt"
2218// lead_in_sample = Factor to increase sample rate in the lead-in section. Default: 10
2219// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
2220// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
2221// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
2222// Example(2DMed): Typical Tooth Profile
2223// pitch = 2;
2224// depth = pitch * cos(30) * 5/8;
2225// profile = [
2226// [-6/16, 0 ],
2227// [-1/16, depth/pitch ],
2228// [ 1/16, depth/pitch ],
2229// [ 6/16, 0 ],
2230// ];
2231// stroke(profile, width=0.02);
2232// Examples:
2233// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2.5, $fn=72);
2234// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2.5, lead_in=1, $fn=72);
2235// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2, lead_in=2, internal=true, $fn=72);
2236// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=1, left_handed=true, lead_in=1, $fn=36);
2237function thread_helix(
2238 d, pitch, thread_depth, flank_angle, turns,
2239 profile, starts=1, left_handed=false, internal=false,
2240 d1, d2, thread_angle,
2241 lead_in_shape,
2242 lead_in, lead_in1, lead_in2,
2243 lead_in_ang, lead_in_ang1, lead_in_ang2,
2244 lead_in_sample=10,
2245 anchor, spin, orient
2246) = no_function("thread_helix");
2247module thread_helix(
2248 d, pitch, thread_depth, flank_angle, turns,
2249 profile, starts=1, left_handed=false, internal=false,
2250 d1, d2, thread_angle,
2251 lead_in_shape,
2252 lead_in, lead_in1, lead_in2,
2253 lead_in_ang, lead_in_ang1, lead_in_ang2,
2254 lead_in_sample=10,
2255 anchor, spin, orient
2256) {
2257 dummy1=assert(num_defined([thread_angle,flank_angle])<=1, "Cannot define both flank angle and thread angle")
2258 assert(is_undef(profile) || !any_defined([thread_depth, flank_angle]),
2259 "Cannot give thread_depth or flank_angle with a profile")
2260 assert(all_positive([turns]), "The turns parameter must be a positive number")
2261 assert(all_positive(pitch), "pitch must be a positive number")
2262 assert(num_defined([flank_angle,thread_angle])<=1, "Cannot give both thread_angle and flank_angle")
2263 assert(is_def(profile) || is_def(thread_depth), "If profile is not given, must give thread depth");
2264 flank_angle = first_defined([flank_angle,u_mul(0.5,thread_angle),15]);
2265 h = pitch*starts*abs(turns);
2266 r1 = get_radius(d1=d1, d=d, dflt=10);
2267 r2 = get_radius(d1=d2, d=d, dflt=10);
2268 profile = is_def(profile) ? profile :
2269 let(
2270 tdp = thread_depth / pitch,
2271 dz = tdp * tan(flank_angle),
2272 cap = (1 - 2*dz)/2
2273 )
2274 assert(cap/2+dz<=0.5, "Invalid geometry: incompatible thread depth and thread_angle/flank_angle")
2275 internal?
2276 [
2277 [-cap/2-dz, tdp],
2278 [-cap/2, 0 ],
2279 [+cap/2, 0 ],
2280 [+cap/2+dz, tdp],
2281 ]
2282 :
2283 [
2284 [+cap/2+dz, 0 ],
2285 [+cap/2, tdp],
2286 [-cap/2, tdp],
2287 [-cap/2-dz, 0 ],
2288 ];
2289
2290 pline = mirror([-1,1], p = profile * pitch);
2291 dir = left_handed? -1 : 1;
2292 attachable(anchor,spin,orient, r1=r1, r2=r2, l=h) {
2293 union(){
2294 zrot_copies(n=starts)
2295 spiral_sweep(pline, h=h, r1=r1, r2=r2, turns=turns*dir, internal=internal,
2296 lead_in_shape=lead_in_shape,
2297 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2,
2298 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
2299 lead_in_sample=lead_in_sample,anchor=CENTER);
2300 }
2301 children();
2302 }
2303}
2304
2305
2306
2307// Questions
2308// Should nut modules take d1/d2 for tapered nuts?
2309//
2310// Need explanation of what exactly the diff is between threaded_rod and helix_threads.
2311//
2312// What about blunt_start for ball screws?
2313// Should default bevel be capped at 1mm or 2mm or something like that? Including/especially inner bevel on nuts
2314
2315// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
2316